看下边这段代码:
Object[] arrays = new String[10]; //1
arrays[0] = 1; //2
arrays[1] = "abc"; //3
编译是否会报错?运行是否会报错?
结果是编译不会报错,运行时第二行报错:java.lang.ArrayStoreException: java.lang.Integer
。
原因是:编译时根据静态类型(引用类型)做类型检查,arrays
的引用类型是Object
数组,所以第二行和第三行都能编译通过。运行时arrays
的实际类型是String
数组,第二行是在往String
数组里添加Integer
元素,所以抛出了异常。
再来看下一段代码:
ArrayList<Object> list = new ArrayList<String>(); //1
list.add(1); //2
list.add("123"); //3
这段代码第一行编译的时候就会报错了。
泛型和数组不一样,持有String
的泛型并不等价于持有Object
的泛型,即使String
是Object
的子类型。
这里泛型和数组有很大的区别,因为虚拟机在运行期和编译器都能得到数组的具体类型信息,对数组中的元素做类型检查。而泛型在运行时已经被擦除了类型信息。无法在运行时做类型检查了。
如果允许上面的代码编译,编译后,就丢失了类型信息,即在运行时list
中持有的是Object
类型的对象,所以上诉代码中的第二行和第三行都能正常运行,那会导致ArrayList<String>
存放了任意类型的元素(这段代码中存放了Integer
和String
)。这显然是不合理的。
因此,Java中,持有String
的泛型不等价于持有Object
的泛型,这是采用类型擦除带来的问题之一。
网友评论