首页 > 代码库 > 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(泛型)