我搜索了我的用例并找到了一些有趣的答案,但它们并不像我需要的那样合适。适当的方法是什么:
@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's answer是正确的。以下代码段可以提供额外的说明。
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);
}
}
当realCast()
无法转换为o
时,使用c
会产生异常。与fakeCast()
相比,只给出了方法的结果类型为T
的承诺。
答案 0 :(得分:8)
我认为这两种方法都是一样的。
不,他们没有。因为在执行时,第一个代码不知道由type erasure引起的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;
}
}
第二个代码以T
的形式知道Class<T>
的类型,因此可以在执行时执行实际演员,正好你正在执行的那一点。
答案 1 :(得分:2)
韦恩(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
。这就是 Real Casting 如乔恩所说。
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
会给短毛猫一个丑陋的Unchecked Cast
警告