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

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

2.java的泛型是由擦拭法实现的,因此有一些局限:

2.1.不能是基本类型,例如int

  • 编译器把T视为Object,Object是无法持有基本类型的

2.2.无法取得带泛型的Class

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);
    }
}
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);
    }
}

java范型的class怎么获取 java范型方法_运维

2.3.无法判断带泛型的Class

java范型的class怎么获取 java范型方法_Pair_02


java范型的class怎么获取 java范型方法_java范型的class怎么获取_03

//判断instance只能使用Pair
public class Main {
    public static void main(String[] args){
        Pair<String> s = new Pair<>("xiaoming","xiaohong");
        Pair<Integer> i = new Pair<>(4,5);
        if(s instanceof Pair){
            System.out.println("true");
        }
    }
}
//判断instance只能使用Pair
public class Main {
    public static void main(String[] args){
        Pair<String> s = new Pair<>("xiaoming","xiaohong");
        Pair<Integer> i = new Pair<>(4,5);
        if(s instanceof Pair){
            System.out.println("true");
        }
    }
}

java范型的class怎么获取 java范型方法_java范型的class怎么获取_04

2.4.不能实例化T类型,因为擦拭后实际上是new Object()

java范型的class怎么获取 java范型方法_java_05

实例化T类型必须借助Class<T>
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(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+")";
    }
}

2.5注意编写的泛型类的方法不要与Object的方法重名

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方法重名。因为范型采用了擦拭法,T擦拭后变成了Object。因此要注意与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;
    }*/
}
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方法重名。因为范型采用了擦拭法,T擦拭后变成了Object。因此要注意与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;
    }*/
}

3.泛型继承:

可以继承子泛型类
父类的类型是Pair
子类的类型是IntPair
Pari.java

package com.testArray;

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first,T last){
        this.first = first;
        this.last = last;
    }
}
package com.testArray;

public class Pair<T> {
    private T first;
    private T last;
    public Pair(T first,T last){
        this.first = first;
        this.last = last;
    }
}

IntPair.java

package com.testArray;

public class IntPair extends Pair<Integer>{
    public IntPair(Integer first,Integer last){
        super(first,last);
    }
}
package com.testArray;

public class IntPair extends Pair<Integer>{
    public IntPair(Integer first,Integer last){
        super(first,last);
    }
}
package com.testArray;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class Main {
    public static void main(String[] args){
        Pair<String> p = new Pair<>("xiao","ming");
        IntPair ip = new IntPair(1,2);
        System.out.println(p instanceof Pair);
        System.out.println(ip instanceof Pair);
        System.out.println(ip instanceof IntPair);
        //getSuperClass()获得该类的父类
        //getGenericSuperclass()获得带有泛型的父类
        //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
        Type type = IntPair.class.getGenericSuperclass();
        //ParameterizedType参数化类型,即泛型
        ParameterizedType pt = (ParameterizedType) type;
        //getActualTypeArguments获取参数化类型的数组,泛型可能有多个
        Type[] types = pt.getActualTypeArguments();
        Class<?> clazz = (Class<?>) types[0];
        /**
         * ? 表示不确定的java类型。 
         * T  表示java类型。 
         * K V 分别代表java键值中的Key Value。 
         * E 代表Element。 
         */
        System.out.println(clazz);
    }
}
package com.testArray;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class Main {
    public static void main(String[] args){
        Pair<String> p = new Pair<>("xiao","ming");
        IntPair ip = new IntPair(1,2);
        System.out.println(p instanceof Pair);
        System.out.println(ip instanceof Pair);
        System.out.println(ip instanceof IntPair);
        //getSuperClass()获得该类的父类
        //getGenericSuperclass()获得带有泛型的父类
        //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
        Type type = IntPair.class.getGenericSuperclass();
        //ParameterizedType参数化类型,即泛型
        ParameterizedType pt = (ParameterizedType) type;
        //getActualTypeArguments获取参数化类型的数组,泛型可能有多个
        Type[] types = pt.getActualTypeArguments();
        Class<?> clazz = (Class<?>) types[0];
        /**
         * ? 表示不确定的java类型。 
         * T  表示java类型。 
         * K V 分别代表java键值中的Key Value。 
         * E 代表Element。 
         */
        System.out.println(clazz);
    }
}

java范型的class怎么获取 java范型方法_java_06

总结:

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