2015-08-28 72 views
1

假設我保持T某一類的子類,的註冊表:如何在運行時獲得通配符上限的類型?

public class ClassRegistry<T> { 
    Set<Class<? extends T>> klasses; 
    ... 
    public void register(Class<? extends T> klass) { 
     klasses.add(klass); 
    } 

你與像registry.register(this.getClass())呼叫註冊自己。我想就這個簡單的與ClassRegistry<T>的方法,你只傳自己,this,如registry.register(this)

public void register(Object obj) { 
     Class<?> klass = obj.getClass(); 
     this.register(klass); 
    } 

哎呀,這是錯誤的,因爲它自稱(匹配與參數類型Object和過載當然不是,Class<? extends T>)。所以,相反:

public void register(Object obj) { 
     Class<? extends T> klass = obj.getClass(); 
     this.register(klass); 
    } 

現在當然不編譯,因爲編譯器不知道你obj實際上是某種類型的? extends T的。這可能不會,因爲主叫方可能是錯的。

所以我的問題是:我如何測試/驗證objT這是一個通配符上限(所以我可以安全地施放)的子類? (我懷疑 - 或許希望 - 答案涉及番石榴的TypeToken,這就是爲什麼我加了番石榴標籤,但我會採取任何答案,謝謝!)

+3

爲什麼'register'接受'Object'而不是'T'? –

+0

有趣的想法 - 如果'T = Class'呢? :) – ZhongYu

+0

@LouisWasserman - 恩,因爲腦屁?無論如何,爲了知道而忽視這一點:我仍然想知道它是如何完成的,因爲我可能有其他理由要知道。 – davidbak

回答

4

您不應該能夠註冊任何對象任何類型,這就是您的register方法所使用的類型Object

我會將該參數的類型更改爲T。然後,您可以保證obj.getClass()將返回Class<? extends T>。編譯器將不太同意,因爲該Javadocs for getClass()狀態:

實際結果類型爲類,其中| X |是調用getClass的表達式的靜態類型的擦除。

調用getClass()的結果是不Class<? extends T>,但Class<? extends Object>(的T擦除)。您可以將它投射到Class<? extends T>,並且會產生未經檢查的投射警告。但是,因爲您現在objT,我認爲類型安全性被保留。

@SuppressWarnings("unchecked") 
public void register(T obj) { 
    Class<? extends T> klass = (Class<? extends T>) obj.getClass(); 
    this.register(klass); 
} 
+0

或只是做它原始 - 'Class klass = obj.getClass();' – ZhongYu

+0

是的,正如我剛剛回答@LouisWasserman上面,我吹了這個簡單的問題,因爲......呃,它正好在午餐之前或什麼。你的回答是我寫'寄存器'方法的正確方法 - 但我仍然想知道如何獲得上限的類型... – davidbak

+1

@davidbak,答案是非常多,你不能因爲擦除。 –