首页 > 代码库 > java学习笔记9.22(泛型)

java学习笔记9.22(泛型)

泛型代码与虚拟机:

自动提供原始类型,擦除类型变量,替换为限定类型(无则用object)

当调用泛型方法时,编译器对返回的object进行强制类型转换

泛型类擦除造成原本在泛型类子类中覆盖的方法变成了重载。(参数类型变成了object)导致子类出现了同一方法名两种参数的方法,调用时本来只希望调用子类的方法(多态),结果有可能调用了泛型超类中的参数为objec的方法。编译器自动在子类中加入桥方法:

public void setSecond(object a){setSecond((Date) a)}

同样在有返回类型的方法中,也会产生两个相同参数类型的方法。虚拟机根据参数类型和返回类型确定一个方法。

一个方法覆盖另一个方法时可以指定一个更加严格的返回类型。

1 虚拟机中没有泛型,只有普通类和方法;2 所有类型参数都用他们的限定类型替换 3 桥方法保持多态 4为保持安全性,必要时插入强制类型转换  

允许泛型代码和遗留代码之间能够互操作。

 

泛型的约束与局限(大多由擦除引起):

1.不能用基本类型实例化类型参数,objec不能储存double的值。

2.运行时的类型查询只适用于原始类型。使用instanceof,getcalss或泛型类型的强制转化时,都是类型擦除后的效果。

3.不能创建参数化类型的数组:Pair<String>[] table=new Pair<String>[10]//error,擦除机制将会导致table数组中可以插入任意的Pair<otherclass>

4.Varargs警告,向参数可变的方法传递一个泛型类型的实例。由于个数可变参数实际上是一个数组,所以会违反第三条,但是只会得到一条警告。

5.不能实例化类型变量:(如果想通过T来构造对象)

new T(),T.class//both error

public Pair(){first=new T();second=new T();}//error

saddly,由于不能调用T.class:

 first=T.class.newInstance()也是错误的

如果非要通过反射调用Class.newInstance来构造泛型对象:在Pair中新建一个泛型方法,由于Class本身是泛型,String.class是Class<String>的一个实例



public
static <T> Pair<T> makePair(Class<T> cl){ try{return new Pair<>(cl.newInstance(), cl.newInstance()) ;} catch(Exception ex){return null;} }
调用:
Pair<String> p = Pair.makePair(string.class);

 不能构造一个类型变量的数组:

public static <T> T[] minmax(T[] a){T[] mm = new T[2];....}//error

6. 泛型类的静态上下文中类型变量无效

7. 不能抛出或捕获泛型类的实例:

泛型类cannot extend throwable;不能catch类型变量(声明中可以throws类型变量)

。。。。

 

 

泛型类型的继承规则:

Pair<employee>和Pair<manager>之间没有关系

Pair<employee> b=Pair<manager> a //error

假设可以转换,则会出现可以在b中存储低级别雇员(由于没有保护)

注意数组和泛型的区别,如果一个manager[]数组赋值给employee[]变量a,则这个变量会带有特别的保护,即低级别雇员无法存储到a[0]。

 

Pair<Employee>时原始类型Pair的一个子类型

泛型类可以扩展或实现其他的泛型类。如ArrayList<T>实现了List<T>接口。

 

通配符类型:

 

java学习笔记9.22(泛型)