java泛型的类型擦除

泛型是JDK1.5时添加的,为了向前兼容,同时不对JVM进行大改,泛型在编译和运行期会擦除类型,这就会导致一些问题。

以数组为例:

String[] s = String[5];
Object[] o = s;
o.add(Object());

我们看这段代码,String数组是不能够添加Obect类型的对象的,运行时数组的具体类型是知道的,所以运行时会报错,编译前检查时不报错。

再来看泛型集合:

List s = ArrayList<>();
List o = s;
o.add(Object()); 
  

由于类型擦除,运行期间并不知道o的具体类型,所以无法报错,只能放到编译前检查时报错。

java中是没有完全的逆变、协变的,List不是List的子类型,为了解决这个问题,就引入了通配符的概念。

extends只能get,不能set:

List s = ArrayList<>();

Object f(List o) {
    o.add("ss"); //编译前检查会报错,由于o的具体类型不知道,只知道是Object的某个子类,不一定是String,所以添加string会报错。
    return o.get(0); //Object类型
}

f(s);


super只能set,不能get:

List o = ArrayList<>();

void f(List s) {
    s.add("ss"); //正确。
    s.get(0); //没问题
    String temp = s.get(0); // 编译前检查会报错,类型不对
}

f(s);

 
  

总结:

无论是数组还是集合,都不能随便使用,无非是编译前还是运行时报错的问题。

你可能感兴趣的:(Java)