廖雪峰Java4反射与泛型-3范型-4擦拭法

擦拭法是Java泛型的实现方式。

  • 编译器把类型 视为Object。
    * 泛型代码编译的时候,编译器实际上把所有的泛型类型T统一视为Object类型。换句话说,虚拟机对泛型一无所知,所有的工作都是编译器做的。
  • 编译器根据 实现安全的强制转型。
    * Java的范型实际是有Java在编译时进行的。编译器内容永远把T视为Object处理,只是在需要转型的时候,根据T的类型实行安全的强制转型。

擦拭法的局限:

  • 1. 不能是基本类型,例如int
    * 编译器把T视为Object,Object是无法持有基本类型的
  • 2.无法取得带泛型的Class
    * 无论T的类型是什么,返回的永远是范型类。如Pair 和Pair 反射获取Class,获取的都是同一个Class:Pair。
public class Main {
    public static void main(String[] args){
        Pair<String> s = new Pair<>("xiaoming","xiaohong");
        Pair<Integer> i = new Pair<>(4,5);

        Class c1 = s.getClass();
        Class c2 = i.getClass();
        System.out.println("c1:"+c1);
        System.out.println("c2:"+c2);

        System.out.print("c1==c2:");
        System.out.println(c1==c2);

        System.out.print("c1 == Pair.class:");
        System.out.println(c1 == Pair.class);
    }
}

  • 3.无法判断带泛型的Class
    对于instanceof的判断,无论哪种方式都提示错误。
    与廖雪峰视频中if (s instanceof Pair.class){}是正常的,但我这提示编译错误。

  • 4.不能实例化T类型,因为擦拭后实际上是new Object()
    • 实例化T类型必须借助Class
    public class Pair<T> {
        private T first;
        private T last;
        public Pair(Class<T> clazz) throws IllegalAccessException,InstantiationException{
       first = clazz.newInstance();
       last = clazz.newInstance();
        }
        public T getFisrt(){
       return first;
        }
        public T getLast(){
       return last;
        }
        public void setFirst(T first){
       this.first = first;
        }
        public void setLast(T last){
       this.last = last;
        }
        public String toString(){
       return "Pari("+first+","+last+")";
        }
    }
    public class Pair<T> {
        private T first;
        private T last;
        public Pair(T first,T last){
       this.first = first;
       this.last = last;
        }
        public T getFirst(){
       return first;
        }
        public void setFirst(){
       this.first = first;
        }
        public T getLast(){
       return last;
        }
        public void setLast(){
       this.last = last;
        }
        public String toString(){
       return "Pair("+first+", "+last+")";
        }
        /**提示与java.lang.Object的equals方法重名。因为范型采用了擦拭法,因此要注意与Object的重名问题
    * 'equals(T)' in 'com.testArray.pair' clashs with 'equals(Object)' in 'java.lang.Object';both methods have same erasure,yet neither overides the other
        public boolean equals(T pair){
       return true;
        }*/
    }
    泛型继承:
    可以继承子泛型类
    父类的类型是Pair
    子类的类型是IntPair

总结:

  • Java的泛型是采用擦拭法实现的
  • 擦拭法决定了泛型 :
    * 不能是基本类型,例如int
    * 不能获取带泛型类型的Class,例如Pair .class
    * 不能判断带泛型类型的类型,例如: x instanceof Pair
    * 不能实例化T类型,例如new T()
    * 泛型方法要防止重复定义方法,例如public boolean equals(T obj)
  • 子类可以获取父类的泛型类型

猜你喜欢

转载自www.cnblogs.com/csj2018/p/10426461.html