[英]How do I build a Java type object at runtime from a generic type definition and runtime type parameters?
假設泛型類型聲明(Java)
class Foo<T> {
public T bar;
}
我怎樣才能在運行時實例化一個Type對象,該對象表示在特定類型T上參數化的Foo(也僅在運行時知道)?
我想我理解你的問題。 您希望序列化Foo<T>
,並且在運行時具有T
的類對象(但在編譯時它並未修復)。 因此,在Gson中建議的創建TypeToken
的匿名子類的解決方案不起作用,因為這要求參數化類型(例如Foo<String>
)在編譯時被硬編碼,並且如果您使用類似Foo<T>
東西它不起作用Foo<T>
。
但是,讓我們看一下Gson站點上的TypeToken
方法實際完成了什么。 您創建一個TypeToken
的匿名子類的TypeToken
,然后使用其getType()
方法請求其類型參數。 類的超類是其元數據的一部分,包括其超類的泛型參數。 因此,在運行時,它可以查看自己的繼承層次結構,並找出用於TypeToken
類型參數,然后返回該類型的java.lang.reflect.Type
實例(如果參數化,將為ParameterizedType
實例)。 獲得此Type
實例后,您應該將其作為toGson()
的第二個參數傳遞。
我們需要做的就是找到另一種方法來創建ParameterizedType
這個實例。 ParameterizedType
是一個接口,但遺憾的是,公共Java API不提供任何具體實現或任何方式來動態創建ParameterizedType
。 似乎有一個名為ParameterizedTypeImpl
的類,在私有Sun API和您可以使用的Gson代碼中( 例如此處 )。 您只需復制代碼並將其重命名為您自己的類。 然后,要在運行時創建表示Foo<String>
的Type
對象,您可以執行類似new ParameterizedTypeImpl(Foo.class, new Type[]{String.class}, null)
(未經測試)
假設我們正在談論List<String>
。
你可以構造這樣的東西:
Type type = new ParameterizedType() {
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
public Type[] getActualTypeArguments() {
return new Type[] { String.class};
}
};
如果您需要這個來從JSON反序列化,您可以使用此Type
來調用gson.fromJson
類型擦除的常用方法是:
class Foo<T> {
Class<T> clazz;
public Foo(Class<T> c) {
clazz = c;
}
public T bar {
return clazz.newInstance();
}
}
如果你的T沒有no-args構造函數,你可以使用Class對象的反射來做更好的事情; 一旦你有一個Class<T>
的實例,你就可以獲得一個實例。
我用gson也遇到了這個問題。 我最終得到了這個:
public class JsonWrapper {
private String className;
private String json; // the output of the gson.toJson() method
}
當我需要反序列化時,我做了一個Class.forName(className)
然后我需要調用gson庫的fromJson()方法。
我無法相信gson本身不支持這一點 - 想要做的事情似乎是一件顯而易見的事情......得到一些json並將其變成一個對象而不知道它是哪個類。
Gson確實為此提供了解決方案: https : //sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener
當然這只是波希米亞語的解決方案(你仍需要以某種方式傳遞類型參數),但是會自動完成。
別人怎么說:)。 要實例化的類需要在運行時可用。 許多方法:將類或類名放在工廠的本地變量中,使用受保護的方法,如果需要在許多不同的地方執行此操作,則創建“對象工廠”類等。這是一種bean框架所做的工作,所以如果你正在使用它,可以通過配置它來實現。
它看起來比大多數人想象的要簡單得多:
Type collectionType = new TypeToken<ArrayList<Person>>(){}.getType();
ArrayList<Person> persons = gson.fromJson(response, collectionType);
無需將ParameterizedTypeImpl類復制為newacct建議。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.