鍍金池/ 教程/ Java/ Java 泛型
Java 數(shù)組
Java 訪問(wèn)器
Java 泛型
Java 方法
指南
Java 動(dòng)態(tài)代理
Java 變量
Java 注解
Java 私有變量和私有方法
Java 動(dòng)態(tài)類加載與重載
java 類
Java 構(gòu)造器

Java 泛型

原文地址

作者: Jakob Jenkov 譯者:葉文海(yewenhai@gmail.com)

內(nèi)容索引

  1. 運(yùn)用泛型反射的經(jīng)驗(yàn)法則
  2. 泛型方法返回類型
  3. 泛型方法參數(shù)類型
  4. 泛型變量類型

我常常在一些文章以及論壇中讀到說(shuō) Java 泛型信息在編譯期被擦除(erased)所以你無(wú)法在運(yùn)行期獲得有關(guān)泛型的信息。其實(shí)這種說(shuō)法并不完全正確的,在一些情況下是可以在運(yùn)行期獲取到泛型的信息。這些情況其實(shí)覆蓋了一些我們需要泛型信息的需求。在本節(jié)中我們會(huì)演示一下這些情況。

運(yùn)用泛型反射的經(jīng)驗(yàn)法則

下面是兩個(gè)典型的使用泛型的場(chǎng)景: 1、聲明一個(gè)需要被參數(shù)化(parameterizable)的類/接口。 2、使用一個(gè)參數(shù)化類。

當(dāng)你聲明一個(gè)類或者接口的時(shí)候你可以指明這個(gè)類或接口可以被參數(shù)化, java.util.List 接口就是典型的例子。你可以運(yùn)用泛型機(jī)制創(chuàng)建一個(gè)標(biāo)明存儲(chǔ)的是 String 類型 list,這樣比你創(chuàng)建一個(gè) Object 的l ist 要更好。

當(dāng)你想在運(yùn)行期參數(shù)化類型本身,比如你想檢查 java.util.List 類的參數(shù)化類型,你是沒(méi)有辦法能知道他具體的參數(shù)化類型是什么。這樣一來(lái)這個(gè)類型就可以是一個(gè)應(yīng)用中所有的類型。但是,當(dāng)你檢查一個(gè)使用了被參數(shù)化的類型的變量或者方法,你可以獲得這個(gè)被參數(shù)化類型的具體參數(shù)。總之:

你不能在運(yùn)行期獲知一個(gè)被參數(shù)化的類型的具體參數(shù)類型是什么,但是你可以在用到這個(gè)被參數(shù)化類型的方法以及變量中找到他們,換句話說(shuō)就是獲知他們具體的參數(shù)化類型。 在下面的段落中會(huì)向你演示這類情況。

泛型方法返回類型

如果你獲得了 java.lang.reflect.Method 對(duì)象,那么你就可以獲取到這個(gè)方法的泛型返回類型信息。如果方法是在一個(gè)被參數(shù)化類型之中(譯者注:如 T fun())那么你無(wú)法獲取他的具體類型,但是如果方法返回一個(gè)泛型類(譯者注:如 List fun())那么你就可以獲得這個(gè)泛型類的具體參數(shù)化類型。你可以在“Java Reflection: Methods”中閱讀到有關(guān)如何獲取Method對(duì)象的相關(guān)內(nèi)容。下面這個(gè)例子定義了一個(gè)類這個(gè)類中的方法返回類型是一個(gè)泛型類型:

  public class MyClass {

  protected List<String> stringList = ...;

  public List<String> getStringList(){
    return this.stringList;
  }
}

我們可以獲取 getStringList()方法的泛型返回類型,換句話說(shuō),我們可以檢測(cè)到 getStringList()方法返回的是 List 而不僅僅只是一個(gè) List。如下例:

Method method = MyClass.class.getMethod("getStringList", null);

Type returnType = method.getGenericReturnType();

if(returnType instanceof ParameterizedType){
    ParameterizedType type = (ParameterizedType) returnType;
    Type[] typeArguments = type.getActualTypeArguments();
    for(Type typeArgument : typeArguments){
        Class typeArgClass = (Class) typeArgument;
        System.out.println("typeArgClass = " + typeArgClass);
    }
}

這段代碼會(huì)打印出 “typeArgClass = java.lang.String”,Type[]數(shù)組typeArguments 只有一個(gè)結(jié)果 – 一個(gè)代表 java.lang.String 的 Class 類的實(shí)例。Class 類實(shí)現(xiàn)了 Type 接口。

泛型方法參數(shù)類型

你同樣可以通過(guò)反射來(lái)獲取方法參數(shù)的泛型類型,下面這個(gè)例子定義了一個(gè)類,這個(gè)類中的方法的參數(shù)是一個(gè)被參數(shù)化的 List:

public class MyClass {
  protected List<String> stringList = ...;

  public void setStringList(List<String> list){
    this.stringList = list;
  }
}

你可以像這樣來(lái)獲取方法的泛型參數(shù):

method = Myclass.class.getMethod("setStringList", List.class);

Type[] genericParameterTypes = method.getGenericParameterTypes();

for(Type genericParameterType : genericParameterTypes){
    if(genericParameterType instanceof ParameterizedType){
        ParameterizedType aType = (ParameterizedType) genericParameterType;
        Type[] parameterArgTypes = aType.getActualTypeArguments();
        for(Type parameterArgType : parameterArgTypes){
            Class parameterArgClass = (Class) parameterArgType;
            System.out.println("parameterArgClass = " + parameterArgClass);
        }
    }
}

這段代碼會(huì)打印出”parameterArgType = java.lang.String”。Type[]數(shù)組 parameterArgTypes 只有一個(gè)結(jié)果 – 一個(gè)代表 java.lang.String 的 Class 類的實(shí)例。Class 類實(shí)現(xiàn)了Type接口。

泛型變量類型

同樣可以通過(guò)反射來(lái)訪問(wèn)公有(Public)變量的泛型類型,無(wú)論這個(gè)變量是一個(gè)類的靜態(tài)成員變量或是實(shí)例成員變量。你可以在“Java Reflection: Fields”中閱讀到有關(guān)如何獲取 Field 對(duì)象的相關(guān)內(nèi)容。這是之前的一個(gè)例子,一個(gè)定義了一個(gè)名為 stringList 的成員變量的類。

public class MyClass {
  public List<String> stringList = ...;
}

Field field = MyClass.class.getField("stringList");

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){
    ParameterizedType aType = (ParameterizedType) genericFieldType;
    Type[] fieldArgTypes = aType.getActualTypeArguments();
    for(Type fieldArgType : fieldArgTypes){
        Class fieldArgClass = (Class) fieldArgType;
        System.out.println("fieldArgClass = " + fieldArgClass);
    }
}

這段代碼會(huì)打印出”fieldArgClass = java.lang.String”。Type[]數(shù)組 fieldArgClass 只有一個(gè)結(jié)果 – 一個(gè)代表 java.lang.String 的 Class 類的實(shí)例。Class 類實(shí)現(xiàn)了 Type 接口。

本文鏈接地址: Java Reflection(九):泛型

上一篇:Java 訪問(wèn)器下一篇:Java 變量