TypeToken獲取運行時泛型類型


 

最近正好使用到了Guava的TypeToken來獲取泛型的類型信息

 

比如,泛型父類需要獲取其子類定義的泛型類型時:

public abstract class GenericClazz<V> {
  
  private Class<V> classType;
  
  public void doSth() {
    final TypeToken<V> typeToken = new TypeToken<V>(getClass()) {};
    classType = (Class<V>) typeToken.getRawType();  //獲得子類的泛型類型
  }
}

 

而使用反射,就稍微復雜了一點。

public abstract class ReflectClazz<V> {
  
  private Class<V> classType;
  
  public void doSth() {
    final Type genType = getClass().getGenericSuperclass();
    classType = (Class<V>) ((ParameterizedType) genType).getActualTypeArguments()[0];  //獲得子類的泛型類型
  }
}

而當繼承類申明的泛型V也是個泛型類,如 public class SubClazz extends ReflectClazz<Map<Integer, String>> {} 這種,使用反射就會更加繁瑣……

 

 

還有一種情況,當我們需要在方法/局部變量中獲取泛型類型時,也可以使用TypeToken:

  public void getGenericType() {
    final TypeToken typeToken = new TypeToken<List<Integer>>() {};
    final Type type = typeToken.getType(); //java.util.List<java.lang.Integer>
  }

上面使用TypeToken的目的是為了在運行時獲取List<T>的泛型類型Integer,反射則辦不到。

(類型擦除機制,.class的LocalVariableTable屬性中只會保留Ljava/util/ArrayList,不會是 Ljava/util/ArrayList<Ljava/lang/Integer;> )

 

TypeToken則不是直接利用反射,而是曲線救國:創建一個TypeToken<T>的匿名繼承類。由於匿名類的申明信息中保留了泛型信息,通過反射可得…

(編譯器不會擦除聲明信息,Signatur屬性中會保存該匿名類的完整信息,如 Lcom/google/common/reflect/TypeToken<Ljava/util/List<Ljava/lang/Integer;>;>; )。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM