2015-10-22 36 views
7

我的代碼:即使我知道它正確返回,爲什麼我必須轉換爲泛型類型T?

private static <T> T get(Class<T> clazz) throws IllegalAccessException, InstantiationException { 
     if (clazz.equals(String.class)) { 
      return (T) new String("abc");//line x 
     } else { 
      return clazz.newInstance(); 
     } 

    } 

正如你看到的,在line xT必須String.class並返回String。但編譯失敗而不會將結果投射到T

變化line x變爲return new String("abc");結果Incompatible types

+1

這實際上不是模板的意思。當然,對你來說顯然它會一直返回類型T的東西 - 但是編譯器很明顯嗎?如果T不是字符串,仍然有一些途徑(可以訪問或不可訪問)返回錯誤的類型。 – JArkinstall

回答

5

編譯器沒有考慮到if語句。

所以它看到的是,你需要返回一個T(其中沒有進一步的知識)。它並沒有推斷這裏T必須是String

可避免你做

return clazz.cast("abc"); 
+0

這不會產生相同的結果。 OP的代碼每次都會創建一個String的新實例,但是您的代碼每次都返回相同的(被阻止的)String。也許'clazz.cast(new String(「abc」));'還應該注意的是調用cast()仍然涉及不安全的強制轉換,但它被埋在了cast方法中。 – Bohemian

+0

@ Bohemian:我靜靜地自動修改了'new String()'部分。在大多數情況下,你不需要一個新的String實例。 'cast'在這裏並不是不安全的,因爲'if'語句已經檢查過類型兼容性(這是這個問題的關鍵,我認爲其他一些語言有更強的類型推斷,將這種條件考慮在內)。 – Thilo

+0

對不起 - 由「不安全」我並不是說從實際的角度來看是不安全的,而是編譯器認爲它是不安全的併產生警告。具體來說,'cast()'方法會返回(T)obj;'並用'@SuppressWarnings(「unchecked」)進行註釋' - 調用'cast()'只是將* *代碼中的警告推入JDK的(我很酷 - 我經常合理地使用這種模式)。 – Bohemian

1

的原因是,你不能施放字符串對每個類別獲得了「未投地擦除型」的警告。想想T是一個Number類,那你會拋出一個ClassCastException。

您可以嘗試使用此方法解決問題:

return (T) ((Object) new String("abc")); 
0

可以避開投如下:

if (clazz.equals(String.class)) { 
    return clazz.getDeclaredConstructor(String.class).newInstance("abc"); 
} 
return clazz.newInstance(); 

你必須趕上(和忽略)少數例外。

相關問題