泛型擦除:
public class ErasedType {public static void main(String[] args) {Class c1 = new ArrayList<String>().getClass();Class c2 = new ArrayList<Integer>().getClass();System.out.println(c1 == c2);}}Arraylsit源码:public class ArrayList<E> extends AbstractList<E>implements List<E>,~Output:true
我们把一个Integer对象放入到String类型的集合中肯定会出错,因为两个集合的类型不同,但他们的class对象比较却是相同。这便是泛型擦除在捣乱。在运行的时候,不管是String类型还是Integer类型都被擦啦。
泛型理解:
在泛型代码内部我们无法获得任何有关泛型参数的信息
当我们在使用泛型时,任何具体的类型信息都被擦除了,我们唯一知道的就是在使用一个对象
无法知道创建摸个对象的特定实例
package com.package15;import java.util.*;class Frob{}class Fnorkle{}class Qurak<Q>{}class Particle<POSITION,MOMENTUM>{}public class LostInformation {public static void main(String[] args) {List<Frob> frobList = new ArrayList<>();Map<Frob,Fnorkle> hashMap = new HashMap<>();Qurak<Frob> Qurak = new Qurak<>();Particle<Frob, Fnorkle> particle = new Particle<>();System.out.println("froblist "+ Arrays.toString(frobList.getClass().getTypeParameters()));System.out.println("hashMap "+Arrays.toString(hashMap.getClass().getTypeParameters()));System.out.println("Qurak " +Arrays.toString(Qurak.getClass().getTypeParameters()));System.out.println("particle "+Arrays.toString(particle.getClass().getTypeParameters()));}}//~Output:froblist [E]hashMap [K, V]Qurak [Q]particle [POSITION, MOMENTUM]
getTypeParameters()用于获取此实体的类型参数。该实体可以是类,数组,接口等。该方法返回表示类型变量的TypeVariable对象的数组。
擦除的核心动机:
非泛化的类库可以去使用泛化的客户端。也就是说,当摸个类库变成泛型时,不会破坏依赖于它的代码和应用程序
擦除的代价:
泛型不能用于显示地引用运行时类型的操做之中,比如:转型、instanceod操做、new 表达式。因为所以关于参数的类型信息都丢失了,无论何时,当我们在编写泛型代码时,必须时刻提醒自己,你只是好像拥有有关参数的类型信息而已。
边界的运用:
1通过泛型使用某一类型的方法?
泛型的擦除机制使我们无法去使用显示的使用运行时类型的操作了。如果我们想要在泛型中使用一个一个类型的方法,那么程序就会报错。↓
问题:public class HasF {public void f(){System.out.println("HasF.f() ");}}class Manipulator<T>{private T o;public Manipulator(T o){this.o = o;}public void manipulate(){o.f();//无法使用类型方法}}public class Manipulation {public static void main(String[] args) {}}
解决方案:使用边界 通过extends来限定边界(!此时要注意对T的初始化),虽然使用边界符可以调用类型方法,但泛型擦除依然存在。
package com.package15;import java.util.Arrays;class HaseF{public void f(){System.out.println("Hase.F()");}}class Manipulator<T extends HaseF>{private T t;Manipulator(T t){this.t=t;}public void info(){t.f();//无法使用泛型类型中的方法的}}public class Manipulation {public static void main(String[] args) {Manipulator<HaseF> haseFManipulator = new Manipulator<>(new HaseF());haseFManipulator.info();//虽然使用边界符可以调用类型方法,但泛型擦除依然存在System.out.println(Arrays.toString(haseFManipulator.getClass().getTypeParameters()));}}
2.通过使用边界,可以返回Woo及其子类,但不需要显示的类型转换。但泛型擦除依然存在。
package com.package15;class Woo{}class Hoo extends Woo{}public class GenericBoundaryApp<T extends Woo> {private T t;GenericBoundaryApp(T t){this.t=t;}public T getTClass(){return t;}public static void main(String[] args) {GenericBoundaryApp<Woo> genericBoundaryApp = new GenericBoundaryApp<>(new Woo());Woo tClass = genericBoundaryApp.getTClass();System.out.println("返回了Woo"+tClass);GenericBoundaryApp<Hoo> genericHoo = new GenericBoundaryApp<>(new Hoo());Hoo tClass1 = genericHoo.getTClass();System.out.println("返回了Woo的子类"+tClass1);}}
