免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
【小家Java】你真的了解Java泛型參數(shù)嗎?細(xì)說java.lang.reflect.Type(ParameterizedType、TypeVariable、WildcardType...)

每篇一句

不要每天看著勵志的句子,過著頹廢的生活

前言

咋一看標(biāo)題,你可能會說。不就是泛型嗎,平時都使用著呢,沒什么難的吧。
感覺了解了,但是真正的深入才知道自己了解甚少!

沒有泛型的時候,只有原始類型。此時,所有的原始類型都通過字節(jié)碼文件類Class類進(jìn)行抽象。Class類的一個具體對象就代表一個指定的原始類型
泛型出現(xiàn)之后,擴(kuò)充了數(shù)據(jù)類型。從只有原始類型擴(kuò)充了參數(shù)化類型、類型變量類型、限定符類型 、泛型數(shù)組類型。

深入了解Java對類型的管理,對我們理解序列化、反序列化的深入理解講非常有幫助。
類型的父類為Type,它位于反射包java.lang.reflect內(nèi)。由JDK1.5之后提供的,它的標(biāo)準(zhǔn)繼承圖譜吐下:


(從左到右)依次是:GenericArrayType(數(shù)組類型)、ParameterizedType(參數(shù)化類型)、WildcardType( 泛型表達(dá)式類型)、TypeVariable(類型變量)、Class(原始/基本類型)

  • Class(原始/基本類型,也叫raw type):不僅僅包含我們平常所指的類、枚舉、數(shù)組、注解,還包括基本類型int、float等等
  • TypeVariable(類型變量):比如List<T>中的T等
  • WildcardType( 泛型表達(dá)式類型):例如List< ? extends Number>這種
  • ParameterizedType(參數(shù)化類型):就是我們平常所用到的泛型List、Map(注意和TypeVariable的區(qū)別)
  • GenericArrayType(數(shù)組類型):并不是我們工作中所使用的數(shù)組String[] 、byte[](這種都屬于Class),而是帶有泛型的數(shù)組,即T[] 泛型數(shù)組

Spring提供了更具統(tǒng)一的類型抽象:ResolvableType,但是本文只講講解JDK的

Type接口本身算是一個標(biāo)記接口,不提供任何需要復(fù)寫的方法

Type的直接子類只有一個,也就是Class,代表著類型中的原始類型以及基本類型。

public interface Type {
    default String getTypeName() {
        return toString();
    }
}

下面就專門針對這些類型做一些案例以及分析~

GenericArrayType(數(shù)組類型)

泛型數(shù)組,描述的是形如:A< T>[]或T[]類型變量和原始類型

public interface GenericArrayType extends Type {
//返回泛型數(shù)組中元素的Type類型,即List<String>[] 中的 List<String>
Type getGenericComponentType();
}

Demo:

public class GenericArrayTypeTest<T> {

    // 這里面有各種各樣的數(shù)組:各有不同 方便看測試效果
    // 含有泛型數(shù)組的才是GenericArrayType
    public void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray, List<String> list,
                                     List<? extends Number> wildcardList, String[] strings, GenericArrayTypeTest[] test) {
    }


    public static void main(String[] args) {
        Method[] declaredMethods = GenericArrayTypeTest.class.getDeclaredMethods();
        for (Method method : declaredMethods) {
            // main方法不用處理
            if (method.getName().startsWith("main")) {
                continue;
            }

            // 開始處理該方法===打印出此方法簽名
            System.out.println("declare Method:" + method); //declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[])

            // 該方法能獲取到該方法所有的實(shí)際的參數(shù)化類型,比如本例中有五個參數(shù),那數(shù)組長度就是5
            Type[] types = method.getGenericParameterTypes();

            // 分組打印出來
            for (Type type : types) {

                if (type instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) type;
                    System.out.println("ParameterizedType type :" + parameterizedType);
                }
                else if (type instanceof GenericArrayType) {
                    // 從結(jié)果

                    GenericArrayType genericArrayType = (GenericArrayType) type;
                    System.out.println("GenericArrayType type :" + genericArrayType);

                    Type genericComponentType = genericArrayType.getGenericComponentType();
                    System.out.println("genericComponentType:" + genericComponentType);
                }
                else if (type instanceof WildcardType) {
                    WildcardType wildcardType = (WildcardType) type;
                    System.out.println("WildcardType type :" + wildcardType);
                }
                else if (type instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) type;
                    System.out.println("TypeVariable type :" + typeVariable);
                }
                else {
                    Class clazz = (Class) type;
                    System.out.println("type :" + clazz);
                }
            }
        }
    }

}

輸出結(jié)果:

declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[])
GenericArrayType type :java.util.List<java.lang.String>[]
genericComponentType:java.util.List<java.lang.String>
GenericArrayType type :T[]
genericComponentType:T
ParameterizedType type :java.util.List<java.lang.String>
ParameterizedType type :java.util.List<? extends java.lang.Number>
type :class [Ljava.lang.String;
type :class [Lcom.fsx.maintest.GenericArrayTypeTest;


分析:GenericArrayType有兩個都是:List<String>[] pTypeArray, T[] vTypeArray它哥倆都是泛型數(shù)組。但是這兩String[] strings, Main[] test可不是,他倆屬于Class普通類型

genericArrayType.getGenericComponentType()返回的類型為ParameterizedTypeImpl類型,能夠獲取到數(shù)組的實(shí)際參數(shù)類型

ParameterizedType(參數(shù)化類型)

參數(shù)化類型,即泛型;例如:List< T>、Map< K,V>等帶有參數(shù)化的對象。

public interface ParameterizedType extends Type {
//獲取類型內(nèi)部的參數(shù)化類型 比如Map<K,V>里面的K,V類型
Type[] getActualTypeArguments();
// 類的原始類型,一般都是Class
Type getRawType();
// 獲取所有者類型(只有內(nèi)部類才有所有者,比如Map.Entry他的所有者就是Map),若不是內(nèi)部類,此處返回null
    Type getOwnerType();
}

Demo:

public class ParameterizedTypeTest {

    private Map<String, ParameterizedTypeTest> map;
    private Set<String> set1;
    private Class<?> clz;
    private Holder<String> holder;
    private List<String> list;
    private ArrayList<String> arrayList; 
    private Map.Entry<String, String> entry;

    private String str;
    private Integer i;
    private Set set;
    private List aList;

    static class Holder<V> {
    }

    public static void main(String[] args) {
        Field f = null;
        try {
            // 拿到所有的字段
            Field[] fields = ParameterizedTypeTest.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];


                if (f.getGenericType() instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
                    System.out.println(f.getName() + ":");

                    System.out.println("\t ParameterizedType:" + Arrays.asList(parameterizedType.getActualTypeArguments()));
                    System.out.println("\t getRawType:" + parameterizedType.getRawType());
                    System.out.println("\t getOwnerType:" + parameterizedType.getOwnerType());
                }
                // 輸出不是ParameterizedType 參數(shù)化類型的
                else {
                    System.out.println(f.getName() + ":is not ParameterizedType ");
                }
            }
        } catch (Exception e) {
        }
    }
}

輸出:

map:
 ParameterizedType:[class java.lang.String, class com.fsx.maintest.ParameterizedTypeTest]
 getRawType:interface java.util.Map
 getOwnerType:null
set1:
 ParameterizedType:[class java.lang.String]
 getRawType:interface java.util.Set
 getOwnerType:null
clz:
 ParameterizedType:[?]
 getRawType:class java.lang.Class
 getOwnerType:null
holder:
 ParameterizedType:[class java.lang.String]
 getRawType:class com.fsx.maintest.ParameterizedTypeTest$Holder
 getOwnerType:class com.fsx.maintest.ParameterizedTypeTest
list:
 ParameterizedType:[class java.lang.String]
 getRawType:interface java.util.List
 getOwnerType:null
arrayList:
 ParameterizedType:[class java.lang.String]
 getRawType:class java.util.ArrayList
 getOwnerType:null
entry:
 ParameterizedType:[class java.lang.String, class java.lang.String]
 getRawType:interface java.util.Map$Entry
 getOwnerType:interface java.util.Map
str:is not ParameterizedType 
i:is not ParameterizedType 
set:is not ParameterizedType 
aList:is not ParameterizedType 

先看最后幾個is not..的。發(fā)現(xiàn)即使是List,但是我們沒給與泛型,它不會是ParameterizedType參數(shù)化類型。
然后holder和entrygetOwnerType不是null,因?yàn)樗麄z類型都是內(nèi)部類,所以有所有者類型。其它的top類都是null
getRawType其實(shí)就是返回了本類的本來的Class類型
getActualTypeArguments:獲取到泛型類型,返回一個數(shù)組(因?yàn)榭赡軙卸鄠€)

WildcardType( 泛型表達(dá)式類型)

通配符表達(dá)式,或泛型表達(dá)式,它雖然是Type的一個子接口,但并不是Java類型中的一種,表示的僅僅是類似 ? extends T、? super K這樣的通配符表達(dá)式。

?—通配符表達(dá)式,表示通配符泛型,但是WildcardType并不屬于Java-Type中的一種

public interface WildcardType extends Type {
//獲得泛型表達(dá)式上界(上限) 獲取泛型變量的上邊界(extends) 
Type[] getUpperBounds();
//獲得泛型表達(dá)式下界(下限) 獲取泛型變量的下邊界(super)
Type[] getLowerBounds();
}

Demo:

public class WildcardTypeTest {

    private List<? extends Number> listUpper;
    private List<? super String> listLower;
    private List<String> list;

    private Map<? extends String, ? super Number> map1;
    private Map<? extends String, ?> map2;

    private Class<?> clazz;
    // 不寫泛型的list
    private List objList;


    private static void printWildcardType(WildcardType wildcardType) {
        for (Type type : wildcardType.getUpperBounds()) {
            System.out.println("\t\t上界:" + type);
        }
        for (Type type : wildcardType.getLowerBounds()) {
            System.out.println("\t\t下界:" + type);
        }
    }

    public static void main(String[] args) {
        Field f = null;
        try {
            Field[] fields = WildcardTypeTest.class.getDeclaredFields();

            for (int i = 0; i < fields.length; i++) {
                f = fields[i];
                System.out.println("begin ******當(dāng)前field:" + f.getName() + " *************************");
                Type genericType = f.getGenericType(); // 獲取字段的泛型參數(shù)
                if (genericType instanceof ParameterizedType) {
                    System.out.println("\tParameterizedType type :" + genericType);

                    ParameterizedType parameterizedType = (ParameterizedType) genericType;

                    for (Type type : parameterizedType.getActualTypeArguments()) {
                        //參數(shù)化類型可能有多個
                        System.out.println("\t  獲取到getActualTypeArguments為:" + type);
                        if (type instanceof WildcardType) {
                            printWildcardType((WildcardType) type);
                        }
                    }
                } else if (genericType instanceof GenericArrayType) {
                    GenericArrayType genericArrayType = (GenericArrayType) genericType;
                    System.out.println("\tGenericArrayType type :" + genericArrayType);
                    Type genericComponentType = genericArrayType.getGenericComponentType();
                    if (genericComponentType instanceof WildcardType) {
                        printWildcardType((WildcardType) genericComponentType);
                    }
                } else if (genericType instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) genericType;
                    System.out.println("\ttypeVariable:" + typeVariable);

                } else {
                    System.out.println("\ttype :" + genericType);
                    if (genericType instanceof WildcardType) {
                        printWildcardType((WildcardType) genericType);
                    }
                }
                System.out.println("end ******當(dāng)前field:" + f.getName() + " *************************");
                System.out.println();
            }
        } catch (Exception e) {
        }
    }
}

輸出:

開始 ******當(dāng)前field:listUpper *************************
ParameterizedType type :java.util.List<? extends java.lang.Number>
  獲取到getActualTypeArguments為:? extends java.lang.Number
上界:class java.lang.Number
結(jié)束 ******當(dāng)前field:listUpper *************************

開始 ******當(dāng)前field:listLower *************************
ParameterizedType type :java.util.List<? super java.lang.String>
  獲取到getActualTypeArguments為:? super java.lang.String
上界:class java.lang.Object
下界:class java.lang.String
結(jié)束 ******當(dāng)前field:listLower *************************

開始 ******當(dāng)前field:list *************************
ParameterizedType type :java.util.List<java.lang.String>
  獲取到getActualTypeArguments為:class java.lang.String
結(jié)束 ******當(dāng)前field:list *************************

開始 ******當(dāng)前field:map1 *************************
ParameterizedType type :java.util.Map<? extends java.lang.String, ? super java.lang.Number>
  獲取到getActualTypeArguments為:? extends java.lang.String
上界:class java.lang.String
  獲取到getActualTypeArguments為:? super java.lang.Number
上界:class java.lang.Object
下界:class java.lang.Number
結(jié)束 ******當(dāng)前field:map1 *************************

開始 ******當(dāng)前field:map2 *************************
ParameterizedType type :java.util.Map<? extends java.lang.String, ?>
  獲取到getActualTypeArguments為:? extends java.lang.String
上界:class java.lang.String
  獲取到getActualTypeArguments為:?
上界:class java.lang.Object
結(jié)束 ******當(dāng)前field:map2 *************************

開始 ******當(dāng)前field:clazz *************************
ParameterizedType type :java.lang.Class<?>
  獲取到getActualTypeArguments為:?
上界:class java.lang.Object
結(jié)束 ******當(dāng)前field:clazz *************************

開始 ******當(dāng)前field:objList *************************
type :interface java.util.List
結(jié)束 ******當(dāng)前field:objList *************************

我們能夠發(fā)現(xiàn),字段的f.getGenericType()絕大部分都是返回的ParameterizedType類型,從而可以繼續(xù)使用getActualTypeArguments拿到具體類型。看看是不是WildcardType類型

像這種private List objList,它f.getGenericType()直接就是interface java.util.List

Map它可以有多個泛型表達(dá)式類型。另外需要說明的一點(diǎn)是:表達(dá)式中,如果你沒有指定上線,默認(rèn)都是有上限的:class java.lang.Object,但是下限不會有默認(rèn)值

泛型中使用 & (并且)操作符

我們不乏有時候能夠看到泛型搭配上 & 的使用方式,比如:

static <R extends Enum<R> & BaseIntEnum> List<R> parse2Enums(...){...}

首先說明一點(diǎn):&不能用于?通配符上(因?yàn)橥ㄅ浞荒芊旁诜盒偷纳昝魃希?br> &只能放在泛型的聲明上。比如類似這種:

public class WildcardTypeTest<T extends Comparable<T> & List<T> & Serializable> { ... }
// 或者方法上申明泛型也成
static <R extends Enum<R> & BaseIntEnum> List<R> parse2Enums(...){...}

需要注意的是,& 后面只能放置接口,而不能是具體類型。連Object都不行

因此當(dāng)我們需要泛型的多重約束的時候,可以使用此并且&操作符。但是它不能用于super上,因?yàn)镴ava有規(guī)定:

class A<T extends Number> is allowed

but

class A<T super Integer> is not allowed

原因請參考:Why super keyword in generics is not allowed at class level
下文也有詳細(xì)分解

TypeVariable(類型變量)

泛型的類型變量,指的是List< T>、Map< K,V>中的T,K,V等值,實(shí)際的Java類型是TypeVariableImpl(TypeVariable的子類;此外,還可以對類型變量加上extend限定,這樣會有類型變量對應(yīng)的上限;值得注意的是,類型變量的上限可以為多個,必須使用&符號相連接,例如 List< T extends Number & Serializable>;其中,& 后必須為接口;

public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
//類型對應(yīng)的上限,默認(rèn)為Object  可以有多個
    Type[] getBounds();
    //獲取聲明該類型變量實(shí)體,也就是TypeVariableTest< T>中的TypeVariableTest
    D getGenericDeclaration();
    //獲取類型變量在源碼中定義的名稱;
    String getName();
    // JDK8新增的
    AnnotatedType[] getAnnotatedBounds();
}

Demo:

public class TypeVariableTest<T extends Number & Serializable, V> {

    private T key;
    private V value;
    // 顯然它本身是個GenericArrayType類型,里面是TypeVariable類型
    private V[] values;
    //ParameterizedType 和 TypeVariable的結(jié)合
    private List<T> tList;

    private String str;


    private static void printTypeVariable(String fieldName, TypeVariable typeVariable) {
        for (Type type : typeVariable.getBounds()) {
            System.out.println("\t\t" + fieldName + ": TypeVariable getBounds " + type);
        }
        System.out.println("\t\t定義Class getGenericDeclaration: " + typeVariable.getGenericDeclaration());
        System.out.println("\t\tgetName: " + typeVariable.getName());
    }

    public static void main(String[] args) {
        Field f = null;
        try {
            Field[] fields = TypeVariableTest.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];
                if (f.getName().equals("log")) {
                    continue;
                }
                System.out.println("開始 ******當(dāng)前field:" + f.getName() + " *************************");
                Type genericType = f.getGenericType();

                if (genericType instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) genericType;
                    for (Type type : parameterizedType.getActualTypeArguments()) {
                        System.out.println("\t獲取ParameterizedType:" + type);
                        if (type instanceof TypeVariable) {
                            printTypeVariable(f.getName(), (TypeVariable) type);
                        }
                    }
                    System.out.println("\tgetOwnerType:" + parameterizedType.getOwnerType());
                    System.out.println("\tgetRawType:" + parameterizedType.getRawType());

                } else if (genericType instanceof GenericArrayType) {
                    GenericArrayType genericArrayType = (GenericArrayType) genericType;
                    System.out.println("GenericArrayType type :" + genericArrayType);
                    Type genericComponentType = genericArrayType.getGenericComponentType();
                    if (genericComponentType instanceof TypeVariable) {
                        TypeVariable typeVariable = (TypeVariable) genericComponentType;
                        printTypeVariable(f.getName(), typeVariable);
                    }
                } else if (genericType instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) genericType;
                    printTypeVariable(f.getName(), typeVariable);
                } else {
                    System.out.println("type :" + genericType);
                }
                System.out.println("結(jié)束 ******當(dāng)前field:" + f.getName() + " *************************");
                System.out.println();
            }
        } catch (Exception e) {
        }
    }

}

輸出:

開始 ******當(dāng)前field:key *************************
key: TypeVariable getBounds class java.lang.Number
key: TypeVariable getBounds interface java.io.Serializable
定義Class getGenericDeclaration: class com.fsx.maintest.TypeVariableTest
getName: T
結(jié)束 ******當(dāng)前field:key *************************

開始 ******當(dāng)前field:value *************************
value: TypeVariable getBounds class java.lang.Object
定義Class getGenericDeclaration: class com.fsx.maintest.TypeVariableTest
getName: V
結(jié)束 ******當(dāng)前field:value *************************

開始 ******當(dāng)前field:values *************************
GenericArrayType type :V[]
values: TypeVariable getBounds class java.lang.Object
定義Class getGenericDeclaration: class com.fsx.maintest.TypeVariableTest
getName: V
結(jié)束 ******當(dāng)前field:values *************************

開始 ******當(dāng)前field:tList *************************
獲取ParameterizedType:T
tList: TypeVariable getBounds class java.lang.Number
tList: TypeVariable getBounds interface java.io.Serializable
定義Class getGenericDeclaration: class com.fsx.maintest.TypeVariableTest
getName: T
getOwnerType:null
getRawType:interface java.util.List
結(jié)束 ******當(dāng)前field:tList *************************

開始 ******當(dāng)前field:str *************************
type :class java.lang.String
結(jié)束 ******當(dāng)前field:str *************************

可以看出:TypeVariable是可以有多個的。可以使用getBounds拿出來,它返回的是數(shù)組(表名是支持多個的嘛)
V雖然啥都沒寫,但是也是有上限:java.lang.Object
普通類型比如String,它啥都木有~~~~屬于Class類型

Class(原始/基本類型)

**Type的直接子類只有一個,也就是Class,代表著類型中的原始類型以及基本類型。**Class —— 反射基石

其意義為:類的抽象,即對“類”做描述:比如類有修飾、字段、方法等屬性,有獲得該類的所有方法、所有公有方法等方法。同時,Class也是Java類型中最重要的一種,表示原始類型(引用類型)及基本類型。

與泛型有關(guān)的類型不能和原始類型統(tǒng)一到Class的原因

產(chǎn)生泛型擦除的原因

原始類型和新產(chǎn)生的類型都應(yīng)該統(tǒng)一成各自的字節(jié)碼文件類型對象。但是由于泛型不是最初Java中的成分。如果真的加入了泛型,涉及到JVM指令集的修改,這是非常致命的(簡單的說就是Java要向下兼容,所以它的泛型是個假東西

Java 引入泛型擦除的原因是避免因?yàn)橐敕盒投鴮?dǎo)致運(yùn)行時創(chuàng)建不必要的類。那我們其實(shí)就可以通過定義類的方式,在類信息中保留泛型信息,從而在運(yùn)行時獲得這些泛型信息。
簡而言之,Java 的泛型擦除是有范圍的,即類定義中的泛型是不會被擦除的

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();

        Type type = map.getClass().getGenericSuperclass(); // 獲取HashMap父類AbstractMap<K,V>  請注意:此處為<K,V>
        ParameterizedType parameterizedType = ParameterizedType.class.cast(type);

        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); // 兩個類型  一個是K,一個是V
        for (Type typeArgument : actualTypeArguments) {
            System.out.println(typeArgument.getTypeName()); //k,v(泛型消失了)
        }
    }


// 泛型不消失的情況對比
public class Main {

    private static class HashMapEx<K, V> extends HashMap<K, V> {
        public HashMapEx() {
            super();
        }
    }

    public static void main(String[] args) {
        // 此處必須用匿名內(nèi)部類的方式寫,如果使用new HashMapEx<String,Integer> 效果同上
        Map<String, Integer> map = new HashMap<String, Integer>() {
        };

        Type type = map.getClass().getGenericSuperclass(); // 獲取HashMapEx父類HashMap<K,V>
        ParameterizedType parameterizedType = ParameterizedType.class.cast(type);

        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); // 兩個類型  一個是K,一個是V
        for (Type typeArgument : actualTypeArguments) {
            System.out.println(typeArgument.getTypeName()); //k,v(泛型消失了)
        }
    }
}

getSuperclass 返回直接繼承的父類(由于編譯擦除,沒有顯示泛型參數(shù))
getGenericSuperclass:返回直接繼承的父類(包含泛型參數(shù)) 1.5后提供

    public static void main(String[] args) {
        // 此處必須用匿名內(nèi)部類的方式寫,如果使用new HashMapEx<String,Integer> 效果同上
        Map<String, Integer> map = new HashMap<String, Integer>() {
        };
        System.out.println(map.getClass().getSuperclass()); //class java.util.HashMap
        System.out.println(map.getClass().getGenericSuperclass()); //java.util.HashMap<java.lang.String, java.lang.Integer>

        // 但是如果是不帶泛型的,兩者等價(jià)
        Integer i = new Integer(1);
        System.out.println(i.getClass().getSuperclass()); //class java.lang.Number
        System.out.println(i.getClass().getGenericSuperclass()); //class java.lang.Number
    }

Java中如何引入泛型

為了使用泛型又不真正引入泛型,Java采用泛型擦除機(jī)制來引入泛型。Java中的泛型僅僅是給編譯器javac使用的,確保數(shù)據(jù)的安全性和免去強(qiáng)制類型轉(zhuǎn)換的麻煩。但是,一旦編譯完成,所有的和泛型有關(guān)的類型全部擦除。

Class不能表達(dá)與泛型有關(guān)的類型

因此,與泛型有關(guān)的參數(shù)化類型、類型變量類型、限定符類型 、泛型數(shù)組類型這些類型編譯后全部被打回原形,在字節(jié)碼文件中全部都是泛型被擦除后的原始類型,并不存在和自身類型對應(yīng)的字節(jié)碼文件。所以和泛型相關(guān)的新擴(kuò)充進(jìn)來的類型不能被統(tǒng)一到Class類中。

與泛型有關(guān)的類型在Java中的表示

為了通過反射操作這些類型以迎合實(shí)際開發(fā)的需要,Java就新增了ParameterizedType, TypeVariable<D>, GenericArrayType, WildcardType幾種類型來代表不能被歸一到Class類中的類型但是又和原始類型齊名的類型。

引入Type的原因

為了程序的擴(kuò)展性,最終引入了Type接口作為Class和ParameterizedType, TypeVariable, GenericArrayType, WildcardType這幾種類型的總的父接口。這樣可以用Type類型的參數(shù)來接受以上五種子類的實(shí)參或者返回值類型就是Type類型的參數(shù)。統(tǒng)一了與泛型有關(guān)的類型和原始類型Class

Type接口中沒有方法的原因

從上面看到,Type的出現(xiàn)僅僅起到了通過多態(tài)來達(dá)到程序擴(kuò)展性提高的作用,沒有其他的作用。因此Type接口的源碼中沒有任何方法。

最后用一個我們最常用的例子:反射獲取泛型類型。給出解決方案如下

反射獲取類的泛型類型

這個還是非常有用的,比如我們在常用的泛型基類設(shè)計(jì)中可以這么寫

public class BaseDaoImpl<T> implements BaseDao<T> {

// 它代表著實(shí)際類型
    private Class<T> beanClass;
    
    @SuppressWarnings("unchecked")
    public BaseDaoImpl() {
        ParameterizedType parameterizedType=(ParameterizedType)this.getClass().getGenericSuperclass();
        beanClass=(Class<T>) parameterizedType.getActualTypeArguments()[0];
    }
    // 省略具體的操作....
}

說明:Class類有兩個"雷同"的方法:

    public native Class<? super T> getSuperclass(); //返回直接繼承的父類(不顯示泛型參數(shù))
    // @since 1.5
    public Type getGenericSuperclass(); // 返回直接繼承的父類 顯示泛型參數(shù)

從返回值或許就能看出差異。他倆從執(zhí)行結(jié)果上,更能看出差異:

Student.class.getSuperclass()class cn.test.Person
Student.class.getGenericSuperclass()cn.test.Person<cn.test.Test>

總結(jié)

我們知道,Type是JDK5開始引入的,其引入主要是為了泛型,沒有泛型的之前,只有所謂的原始類型。此時,所有的原始類型都通過字節(jié)碼文件類Class類進(jìn)行抽象。Class類的一個具體對象就代表一個指定的原始類型。

泛型出現(xiàn)之后,也就擴(kuò)充了數(shù)據(jù)類型。從只有原始類型擴(kuò)充了參數(shù)化類型、類型變量類型、泛型數(shù)組類型,也就是Type的子接口
  那為什么沒有統(tǒng)一到Class下,而是增加一個Type呢?(Class也是種類的意思,Type是類型的意思)
  
  是為了程序的擴(kuò)展性,最終引入了Type接口作為Class,ParameterizedType,GenericArrayType,TypeVariable和WildcardType這幾種類型的總的父接口。
  這樣實(shí)現(xiàn)了Type類型參數(shù)接受以上
五種子類的實(shí)參
或者返回值類型就是Type類型的參數(shù)。

List<T ? entends>[]:這里的List就是ParameterizedType,T就是TypeVariable,T ? entends就是WildcardType(注意,WildcardType不是Java類型,而是一個表達(dá)式),整個List<T ? entends>[]就是GenericArrayType


文章來源:https://blog.csdn.net/f641385712/article/details/88789847

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JAVA反射總結(jié)
談?wù)凧ava類型中ParameterizedType,GenericArrayType,TypeVariabl,WildcardType
java基礎(chǔ)之反射類型Type
關(guān)于Java如何讀取泛型類型參數(shù)
Classworking 工具箱: 反射泛型
Java 運(yùn)行時如何獲取泛型參數(shù)的類型
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服