簡體   English   中英

鑄造一個通用類。 (演員)vs Class.cast()

[英]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解釋得很清楚。 我想在這里添加一個例子,以便可以清楚地觀察到差異

Class.cast()

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM