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

mr.*_*r.b 6 java generics casting

我搜索了我的用例并找到了一些有趣的答案,但它们并不像我需要的那样合适.适当的方法是什么:

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

或者有点不同:

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

我认为这两种方法都是一样的.从我的观点来看,方法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);
    }
}
Run Code Online (Sandbox Code Playgroud)

无法转换realCast()时,使用生成异常.相比之下,只给出了方法的结果是类型的承诺.ocfakeCast()T

Jon*_*eet 8

我认为这两种方法都是一样的.

不,他们没有.因为在执行时,第一个代码不知道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;
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个代码知道T形式的类型Class<T>,因此它可以在执行时执行真实演员,恰好在您执行它的时候.

  • @mr.b:不,`fakeCast()` 本身根本不会*。方法中的强制转换完全没有任何作用。只是当一个方法返回 `T` 时,它实际上只返回 `Object`,并且如果 *calling* 代码实际上使用返回值作为 `T`,它会进行转换。请注意第一次调用如何不会导致异常。 (2认同)