2013-04-28 31 views
0

我想編寫通用代碼來解析用戶輸入並將其與類數組進行比較,然後相應地投射輸入。即:從BufferedReader(InputReader)輸入解析Integer.class

  1. 對象[] paramTypes = {String.class,String.class,Integer.class}
  2. 對象[] userInput = { 「playerName1」, 「targetPlayerName」, 「5」} // 5是字符串
  3. 用戶輸入的每個字符串都轉換爲paramTypes中的相應類。
  4. 最後,將轉換的單詞放入另一個Object [] castedUserInput中供以後使用。

    for(int i = 0; i<userInput.length; i++) 
        castedUserInput[i] = paramTypes[i].cast(userInput[i]); 
    
問題:

只要paramTypes [i]是Integer.class並且執行投,一個ClassCastException發生。該異常的文檔讀取:

ClassCastException異常:拋出,表明代碼已經試圖對象轉換子類,它是不是一個實例

所以,既不(對象)「5」 (爲什麼這不起作用?)也不能將「5」轉換爲Number的子類。

現在我明白,數字和字符串都是對象的子類,但除此之外彼此不相關。我正在安裝JDK7來查看的源代碼ClassCastException,但我懷疑這對於我只編程了大約一年並且缺乏對什麼java編譯器和虛擬機正在這裏做着。

任何人都可以幫助我嗎? PS:當然可以使用幾個if子句,然後使用Integer.parseInt(userInput [i]),Long.parseLong(userInput [i])等,但這不可能是最有效的解決方案,對?

+1

沒有調用解析功能,是如何知道如何改變一個任意字符串爲整數計算機?從編譯器的角度來看,它無法區分「4」和「一些隨機字符串」。 (雖然顯然你不能將後者轉換爲int) – 2013-04-28 21:32:02

+1

將對象轉換爲另一種類型決不會改變對象的類型。它所做的只是允許你引用另一個類型的對象,當且僅當它真的具有這種類型。一個字符串是一個字符串,一個CharSequence,一個Serializable,一個COmprable和一個對象,但它不是一個整數。 – 2013-04-28 21:34:55

回答

1

由於輸入的類型爲String,並且String不能轉換爲Integer,所以您將得到類別轉換異常。您應該查看轉換爲預期參數類型的輸入,而不是轉換。爲此目的有幾個框架,但如果您只有有限數量的可能類型,您可以自己寫一些東西。而Integer/Long.parseInt將是一個解決方案。

1

正如你正確地指出的那樣,這裏的問題是作爲字符串的「5」被轉換爲整數。由於Integer不是String的子類,因此JVM在運行時拋出ClassCasrException。 Integer和String都是Object的子類,因此將String和Integer值轉換爲Object是安全的(正如在Object數組中存儲字符串或整數時所做的那樣)。修復

一種方法使用起來會:

for(int i = 0; i<userInput.length; i++) 
    castedUserInput[i] = safeCast(paramTypes[i], userInput[i]); 

其中safeCast()執行轉換爲您可能使用如果您提及的條款來解析成的int,long等另一種方法,這恕我直言更泛型,將使用反射並調用接受String參數的構造函數。大部分具體的Number類(Byte,Double,Float,Integer,Long,Short)都支持這樣的構造函數,所以你應該對Number類很好。對於自定義類,您將需要一個構造函數來接受一個String參數。下面是一個使用反射和依賴於擁有一個構造函數,需要傳遞的值作爲參數解決方案:

public static Object safeCast(Class paramType, Object value) 
     throws NoSuchMethodException, IllegalAccessException, 
     InvocationTargetException, InstantiationException { 
    if (value == null) { 
     return null; 
    } 
    final Class<?> valueClass = value.getClass(); 
    if (paramType.isAssignableFrom(valueClass)) { 
     return value; 
    } 
    final Constructor theConstructor = paramType.getConstructor(valueClass); 
    return theConstructor.newInstance(value); 
}