qq_22246675
2017-09-12 09:52 阅读 1.6k

JAVA泛型的问题:急求大神。一个关于"泛型"和Object[]数组的坑

下面是我写的一个Java代码,
图片说明
我知道24行的直接转换是不行的,因为内部数组本质是一个Object[]的数组,但是运行该程序是会报错的,报错的位置是在25行,错误信息是类型转换错误。但是26行这样的写法是没有问题的,如果将25行注释掉,程序可以正常运行。我想知道的是25和26行代码区别在哪里,为什么25行是会报错的,是编译器做了什么事情吗?我看过这个源代码编译后的class文件,25行加入了一个类型检查,但是为什么会加上类型检查?挺急的,跪求大神解答。

源代码如下:
public class GenericArray {

private Object[] array;

public GenericArray(int size) {
    array = new Object[size];
}

public void put(int index, T item) {
    array[index] = item;
}

public T get(int index) {
    return (T) array[index];
}

public T[] rep() {
    return (T[]) array;
}

public static void main(String[] args) {
    GenericArray<Integer> ga = new GenericArray<>(10);
    for(int i = 0; i < 10; i++) {
        ga.put(i, i);
    }
    for(int i = 0; i < 10; i++) {
        System.out.println(ga.get(i) + " ");
    }
    System.out.println();
    try {
        System.out.println(ga.rep().toString());
        System.out.println(((Object)ga.rep()).toString());
    } catch(Exception e) {
        e.printStackTrace();
    }
}

}

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

8条回答 默认 最新

  • tomorrow_fine 无名同学 2017-09-12 12:37

    我们无法获知类型T是否含有方法toString()方法。这是为什么呢?就是因为万恶的擦除引起的,在Java代码运行的时候,它会将泛型类的类型信息T擦除掉,就是说运行阶段,泛型类代码内部完全不知道类型参数的任何信息,即使toString()是object的方法。

    点赞 3 评论 复制链接分享
  • c15158032319 外星喵 2017-09-12 14:24
        @Test
        public void test(){
            Integer[] ii = new Integer[]{};
            Object[] oo = new Object[]{};
            ii = (Integer[])oo;
        }
    
    

    事实是因为你的array真实类型是Object[],所以此处强转为Integer[]会报错。除非arry = new Integer[]{},那么这里转换就不会报错了。

    点赞 1 评论 复制链接分享
  • fanyizhuang 闪现送五杀 2017-09-12 09:59

    用String.valueOf(ga2.rep())看下

    点赞 评论 复制链接分享
  • Small_Mouse0 鼠小 2017-09-12 10:02

    报的什么错,,,感觉不应该呀,,,题主能把代码发一下吗?

    点赞 评论 复制链接分享
  • phenomenonsTell 我也不知道该叫啥 2017-09-12 11:22

    这样就不会报错了,你的那个rep()方法想要返回数组的话直接调用Arrays工具类的方法就行。
    我的eclipse的输出结果:
    0 1 2 3 4 5 6 7 8 9
    GenericArray [array=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

     import java.util.Arrays;
    
    public class GenericArray<T> {
        private T[] array;
    
        public GenericArray(int size) {
            array = (T[]) new Object[size];
        }
    
        public void put(int index, T item) {
            array[index] = item;
        }
    
        public T get(int index) {
            return array[index];
        }
    
        @Override
        public String toString() {
            return "GenericArray [array=" + Arrays.toString(array) + "]";
        }
    
        public static void main(String[] args) {
            GenericArray<Integer> ga = new GenericArray<>(10);
            for(int i = 0; i < 10; i++) {
                ga.put(i, i);
            }
            for(int i = 0; i < 10; i++) {
                System.out.print(ga.get(i) + " ");
            }
            System.out.println();
            try {
                System.out.println(ga.toString());
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    点赞 评论 复制链接分享
  • weixin_40214842 weixin_40214842 2017-09-12 13:21

    发来看一下帮你试一下

    点赞 评论 复制链接分享
  • luaifei2008 luaifei2008 2017-09-12 14:57

    首先,子类数组转父类数组没问题,如 String[] s; 可以转为 Object[] o = (Object[])s;
    但父类数组不能转成子类数组,因为不能保证父类的元素都符合子类类型,因为同一个父类可以有不同的子类

    所以
    第一种情况,Object[] o是确定的类型,String[] s也是确定的类型,所以编译期间编译器能知道父类数组不能转成子类数组,所以报错

    而第二种是泛型擦除
    Object[] o是确定的类型,T[] t是泛型,编译的时候编译期不知道T[]是什么类型,而把泛型擦除,即把T[]变为Object[](Object[]是父类数组没问题),所以编译器只是给出警告

    参考链接:http://bbs.csdn.net/topics/390028191

    点赞 评论 复制链接分享
  • u011857460 sagittar_zhang 2017-09-13 01:27

    3行定义,改成T[] array

    点赞 评论 复制链接分享

相关推荐