2012-03-05 70 views
0

我有一個完整的stumper,並將其提供給所有人,看看你是否知道發生了什麼事情。未能強制在Java通用類型

這是數據結構

Map<String, Object> objectMap 

它存儲字符串和數值現在,但可能在未來存儲更多類型。

這是我用來檢索這些值的函數:

public <T> T get(String variable, T defaultValue) { 
    // returns either the object from the map, or the default if its not in the map. 
    Object value = getObject(variable, defaultValue); 
    logger.debug("default value is of type " + defaultValue.getClass().getName()); 

    // Attempt to get around casting issue 
    if (value instanceof Number) 
    { 
     value = (Number) value; 
    } 
    T ret = (T) value; 
    logger.debug("Variable " + variable + " which is of type " + value.getClass().getName() + " and returning as " + ret.getClass().getName() + " (is number: " + (value instanceof Number) + ")"); 

    return ret; 
} 

這是調用代碼:

public int getFoo() { return this.<Integer>get("foo", 0); } 

這是輸出我在日誌中看到:

default value is of type java.lang.Integer 
Variable foo which is of type java.lang.Long and returning as java.lang.Long (is number: true) 

就在它失敗之前:

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer 

這裏最讓我擔心的是類的類型看起來很長,儘管試圖強制類使用Integer

我錯過了什麼,或者違反了Java泛型的一些概念?

感謝所有幫助

+0

對於初學者,你真的不應該使用'Map '。地圖應該有一個單一的,具體的價值類型,它真的是有代碼的臭混合在一起。 – 2012-03-05 08:14:02

+0

請發送更多堆棧跟蹤,發生此異常? – MJM 2012-03-05 08:18:40

+0

對地圖的看法是什麼? – 2012-03-05 08:19:21

回答

1

getObject方法返回的值爲java.lang.Long - 日誌告訴你。泛型不是魔術,它們不會在類型之間進行轉換,它們只是編譯器轉換爲強制轉換的語法糖。所以,你的方法:

public <T> T get(String variable, T defaultValue) 

是真的:

this.<Integer>get("foo", 0) 

這是真的:

(Integer)this.get("foo", 0) 

因此,ClassCastException異常

public Object get(String variable, Object defaultValue) 

當get方法與調用因爲返回的是Long,而不是Integer

不知道你想要達到什麼目的很難給出具體的建議,但通常你的Map應該使用你期望處理的泛型類型。在你的情況下,這聽起來像IntegerNumber。如果你真的需要任何Number的int值(我懷疑是因爲值大於int時會被截斷),那麼你應該使用Number.intValue()方法。

+0

這是我一直在尋找的anser。我想到了這一點。 強制函數中的類型變爲整數,而不是成爲一個表演。 – cyberconte 2012-03-05 08:59:36

+0

當呼叫正在執行時,這。 get(「foo」,0) 被轉換爲(Integer)this.get(「foo」,0)。但即使是動態的,這種轉換也不如泛型所執行的那樣:在方法實現中可以進一步轉換。 – DaveFar 2012-03-05 12:40:00

0

這是由Java類型擦除造成的。 Java類型僅用於源代碼。編譯器會轉換代碼,就好像您要投射所有對象一樣。如果您獲得Long值,則表示您將其作爲Long值。

此代碼不能執行任何東西:

if (value instanceof Number) 
{ 
    value = (Number) value; 
} 
0

在底層映射中的關鍵「富」的值是Long類型明顯。你不能將Long轉換爲Integer(即使它們都是Number類型 - 都是Object類型)

如果你想強制一個Integer,你必須在將「foo」進入地圖。