[英]Creating parameterized type object using anonymous class
這可能是一個愚蠢的問題,但我剛剛看到一個問題,詢問如何為泛型 type 創建一個 Type 變量。 共識似乎是你應該有一個返回該類型的虛擬方法,然后使用反射來獲取它(在這種情況下他想要Map<String, String>
)。 像這樣的事情:
public Map<String, String> dummy() { throw new Error(); }
Type mapStringString = Class.forName("ThisClass").getMethod("dummy").getGenericReturnType();
我的問題是,沒有那么多使用反射,你不能做這樣的事情:
Type mapStringString = new ParameterizedType() {
public Type getRawType() {
return Map.class;
}
public Type getOwnerType() {
return null;
}
public Type[] getActualTypeArguments() {
return new Type[] { String.class, String.class };
}
};
這行得通嗎? 如果沒有,為什么不呢? 如果確實如此,會有哪些危險/問題(除了能夠返回某些類型,如Integer<String>
這顯然是不可能的。
當然可以,而且對於大多數應用程序來說,這可能就足夠了。
但是,使用第一種方法,您可以獲得更精致的對象。 例如,假設您使用第一種方法創建對象type1
,使用第二種方法創建對象type2
。 然后type1.equals(type2)
將返回 true(因為第一個方法返回一個正確實現 equals 方法的對象)但type2.equals(type1)
將返回 false(因為在第二個方法中,您沒有覆蓋 equals -method,並且正在使用Object
的實現)。
同樣的推理適用於其他(有時有用的方法),例如toString
、 hashCode
等。第二種方法不提供這些的有用實現。
如果您的項目中包含 Google 的Guava庫(您應該這樣做;它很棒),請使用它的TypeToken
來獲取類型。 Google 的Gson庫(用於與 JSON 交互)有一個類似的版本。 兩者都像這樣使用(獲取表示List<String>
的Type
:
Type t = new TypeToken<List<String>>(){}.getType();
如果您不想依賴任何第三方庫,您仍然可以使用匿名類型通過一行代碼獲得通用的具體類型(這種技術不適用於接口,並且可能比 Abstract 的價值更麻煩類型)。 要獲取表示HashMap<String, String>
的Type
,請執行以下操作:
Type t = new HashMap<String, String>(){}.getClass().getGenericSuperclass();
我已經驗證生成的Type
實例.equals()
是由Gson的TypeToken
創建的Type
實例,但尚未驗證Guava版本的TypeToken
,我目前無法訪問。 (Guava 是一個更通用的庫,它對各種事情都非常方便,無論如何你都應該使用它。)
實際上,我認為最簡單的方法(==最少代碼)是一個擴展您感興趣的類型的虛擬接口,然后從它的類中獲取getGenericInterfaces()[0]
getGenericSuperclass()
如果您感興趣,請使用getGenericSuperclass()
一類):
private interface MapStringString extends Map<String, String> {}
private static ParameterizedType mapStringString(){
return (ParameterizedType) MapStringString.class.getGenericInterfaces()[0];
}
但是,它不能很好地擴展,因為您必須為要表示的每個ParameterizedType
創建一個新類。 我不明白為什么你的實現不會做(除非在某處有縮小強制轉換),而且它確實有一個吸引人的好處,你可以使它可重用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.