简体   繁体   English

铸造一个通用类。 (演员)vs Class.cast()

[英]Casting a generic class. (cast) vs Class.cast()

I have searched for my use case and found some interesting answers but they are not as suitable as i need. 我搜索了我的用例并找到了一些有趣的答案,但它们并不像我需要的那样合适。 What would the appropriate way to do this: 适当的方法是什么:

@SuppressWarnings("unchecked")
public <T> T newInstance(String name) throws ClassCastException, InstantiationException, IllegalAccessException, ClassNotFoundException {
    return (T) loadClass(name).newInstance();
}

or a little different: 或者有点不同:

public <T> T newInstance(String name, Class<T> c) throws ClassCastException, InstantiationException, IllegalAccessException, ClassNotFoundException {
    return c.cast(loadClass(name).newInstance());
}

I think that both methods do the same. 我认为这两种方法都是一样的。 From my point of view method 1 is better because of less parameters. 从我的观点来看,方法1因为参数较少而更好。 Boths throw a ClassCastException which will be fine for me. 两者抛出一个ClassCastException对我来说没问题。 Truly, the @SuppressWarnings("unchecked") annotation is not nice. 确实, @SuppressWarnings("unchecked")注释并不好。

Can someone tell me if there are any advantages for one method towards the other? 有人能告诉我一种方法对另一种方法有什么好处吗?

Edit: Jon Skeet's answer is correct. 编辑: Jon Skeet的回答是正确的。 The following snippet can provide additional clarification. 以下代码段可以提供额外的说明。

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);
    }
}

Using realCast() produces an Exception when o can't be cast to c . o无法转换为c时,使用realCast()会产生异常。 In comparison to that fakeCast() only gives a promise that the method's result is type of T . fakeCast()相比,只给出了方法的结果是T类型的承诺。

I think that both methods do the same. 我认为这两种方法都是一样的。

No, they don't. 不,他们没有。 Because at execution time, the first code doesn't know the type of T due to type erasure . 因为在执行时,第一个代码由于类型擦除而不知道T 类型 That means the cast basically does nothing within the method. 这意味着演员在方法中基本上什么都不做。 The calling code might implicitly cast to whatever T it is specifying, but if the caller is another generic method (with the T used here as another type parameter), even that wouldn't want. 调用代码可能隐式地转换为它指定的任何T ,但是如果调用者是另一个泛型方法(这里使用T作为另一个类型参数),即使这不需要。

Here's a simple example of that: 这是一个简单的例子:

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;
    }
}

The second code knows the type of T in the form of Class<T> , so it can perform a real cast at execution time, at exactly the point you're performing it. 第二个代码以Class<T>的形式知道T的类型,因此它可以在执行时执行真正的转换, 恰好在您执行它的时候。

Well explained answer by Jon Skeet. Jon Skeet解释得很清楚。 I'd like to add an example here so that the differences can be observed clearly 我想在这里添加一个例子,以便可以清楚地观察到差异

Class.cast() 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)
      }
}

Output: 输出:

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

Down-casting Object.class object to String.class is illegal here as they are not compatible. 向下转换Object.class对象到String.class是非法的,因为它们不兼容。

By using Class.cast() , the casting does take place in castMethod() and hence throws ClassCastException . 通过使用Class.cast()转换确实发生在castMethod() ,因此抛出ClassCastException That's what the Real Casting means as stated by Jon. 这就是乔恩所说的真正的铸造意味着什么。


Cast Operator 演员

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;
     }
}

Output: 输出:

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

From the output, you can see that the ClassCastException is thrown at main() , unlike Class.cast() which throws exception at castMethod() . 从输出中可以看出ClassCastException是在main()处抛出的,不像Class.cast()在castMethod()处抛出异常。 That's why Jon named it as Fake Casting , as the casting is actually done when the result of castMethod is assigned to the String variable. 这就是为什么Jon将其命名为Fake Casting ,因为当castMethod的结果被赋值给String变量时,实际上就完成了转换。 If the castMethod is called with the result being ignored, no exception will be seen at all. 如果调用castMethod并忽略结果,则根本不会看到任何异常。

Also, return (T) o will give you an ugly Unchecked Cast warning from the linter 此外, return (T) o将为您提供来自linter的丑陋的Unchecked Cast警告

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM