[英]Casting a generic class. (cast) vs Class.cast()
我搜索了我的用例並找到了一些有趣的答案,但它們並不像我需要的那樣合適。 適當的方法是什么:
@SuppressWarnings("unchecked")
public <T> T newInstance(String name) throws ClassCastException, InstantiationException, IllegalAccessException, ClassNotFoundException {
return (T) loadClass(name).newInstance();
}
或者有點不同:
public <T> T newInstance(String name, Class<T> c) throws ClassCastException, InstantiationException, IllegalAccessException, ClassNotFoundException {
return c.cast(loadClass(name).newInstance());
}
我認為這兩種方法都是一樣的。 從我的觀點來看,方法1因為參數較少而更好。 兩者拋出一個ClassCastException
對我來說沒問題。 確實, @SuppressWarnings("unchecked")
注釋並不好。
有人能告訴我一種方法對另一種方法有什么好處嗎?
編輯: Jon Skeet的回答是正確的。 以下代碼段可以提供額外的說明。
public class Test {
public static void main(String[] args) {
Object o = new Object();
// Exception at c.cast(o)
Test.<String>realCast(o, String.class);
}
private static <T> T realCast(Object o, Class<T> c) {
return c.cast(o);
}
}
當o
無法轉換為c
時,使用realCast()
會產生異常。 與fakeCast()
相比,只給出了方法的結果是T
類型的承諾。
我認為這兩種方法都是一樣的。
不,他們沒有。 因為在執行時,第一個代碼由於類型擦除而不知道T
類型 。 這意味着演員在方法中基本上什么都不做。 調用代碼可能隱式地轉換為它指定的任何T
,但是如果調用者是另一個泛型方法(這里使用T
作為另一個類型參數),即使這不需要。
這是一個簡單的例子:
public class Test {
public static void main(String[] args) {
Object o = new Object();
// No exception
Test.<String>fakeCast(o);
// Exception at the point of assignment:
// the code is effectively String x = (String) ...;
String x = Test.<String>fakeCast(o);
}
private static <T> T fakeCast(Object o) {
return (T) o;
}
}
第二個代碼以Class<T>
的形式知道T
的類型,因此它可以在執行時執行真正的轉換, 恰好在您執行它的時候。
Jon Skeet解釋得很清楚。 我想在這里添加一個例子,以便可以清楚地觀察到差異
public class Test{
public static void main(String[] args){
Object o = new Object();
Test.castMethod(o, String.class); //Exception is thrown here
}
public static <T> T castMethod (Object o, Class<T> tClass){
return tClass.cast(o)
}
}
輸出:
Exception in thread "main" java.lang.ClassCastException: Cannot cast java.lang.Object to java.lang.String
at java.base/java.lang.Class.cast
at com.test.Test.castMethod
向下轉換Object.class
對象到String.class
是非法的,因為它們不兼容。
通過使用Class.cast()
, 轉換確實發生在castMethod()
,因此拋出ClassCastException
。 這就是喬恩所說的真正的鑄造意味着什么。
public class Test{
public static void main(String[] args){
Object o = new Object();
Test.<String>castMethod(o); //No Exception
String x = Test.<String>castMethod(o); //Exception is thrown here
}
public static <T> T castMethod(Object o){
return (T) o;
}
}
輸出:
Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Object cannot be cast to java.base/java.lang.String
at com.test.Test.main
從輸出中可以看出ClassCastException
是在main()
處拋出的,不像Class.cast()在castMethod()
處拋出異常。 這就是為什么Jon將其命名為Fake Casting ,因為當castMethod
的結果被賦值給String變量時,實際上就完成了轉換。 如果調用castMethod
並忽略結果,則根本不會看到任何異常。
此外, return (T) o
將為您提供來自linter的丑陋的Unchecked Cast
警告
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.