java-泛型-为什么不能使用new操作

java-泛型-extends和super

    • 前言
    • 类型擦除
    • extends和super
    • 总结

前言

昨天写数据结构-数组的时候想要写这样一段代码:

public class BaseArray<T> {
    private int length;
    private T[] array;
    BaseArray(int length) {
        this.length = length;
        array = new T[length];
    }
}

array = new T[length];这里是不能通过编译的。当时没有细想,所以当时放弃了使用泛型。闲暇之余又想起了这个问题,现在终于弄清楚了这个问题,原来是类型擦除引起的。搜集擦除问题的时候,发现大量泛型-extends和super的问题,这个自己是知道基本概念的,一个是上限通配符,一个是下限通配符,也知道一个不能add,一个不能get,之前自己是有弄清楚这个问题的,现在有所遗忘,所以再一次巩固。

类型擦除

  • Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉。Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程成为类型擦除。如在代码中定义List和List等类型,在编译后都会变成List,JVM看到的只是List,而由泛型附加的类型信息对JVM是看不到的。
  • 泛型不能用于显性地引用运行时类型的操作之中,例如转型,instanceofnew操作(包括new一个对象,new一个数组),因为所有关于参数的类型信息都在运行时丢失了,所以任何在运行时需要获取类型信息的操作都无法进行工作。
    借用网上的一个例子:
public class Abrasion {
    public static void main(String[] args) {
        Class a = new ArrayList<Integer>().getClass();
        Class b = new ArrayList<String>().getClass();
        System.out.println(a == b);
    }
}

以上代码返回:true

extends和super

这个网上有很多的资料,这里就不重复说明,有两句话可以有助于理解:

  • 上限通配符,用来限制类型的上限。List list 你可以理解为这个list可能是List也可能是List或List,只要是Fruit或其子类就行,这时候你要存入一个Orange,也就是add操作的时候,这样是不行的,因为编译器判断不了你这个List是Apple还是Orange还是Banana(因为都可以),所以就只能什么都不能存(null除外),但是使用get获取到的都具有Fruit特性。
  • 下限通配符,用来限制类型的下限。List list你可以理解为这个list可能是List或List,所以编译器允许你存Fruit或其子类,也就是add操作,而get的类型默认都是Object。

总结

泛型有很多的资料,并且都有不错的代码例子,但是前期可能不好理解,所以需要多多使用,可以先记住简单的结论,以后使用中就可以自然彻底理解。
适用于使用父类特性,重点在于使用,读取内容。不适合add
适用于保存具有父类特性的子类,重点在于保存,写入内容。不适合get

你可能感兴趣的:(开发规范)