为什么这样做?
@SuppressWarnings("unchecked")
public <T> T getResult(Class annotated) {
return (T) getResult(annotated, new HashMap<String, Object>(0));
}
编译器如何知道如何转换返回值?它在编译时无法知道它:它可能是任何东西。它是否每次都在运行时执行?
答案 0 :(得分:4)
如果可能的话,泛型方法中T
的类型是从调用的上下文推断出来的。
String string = foo.getResult(Something.class);
如果无法从上下文中确定T
的类型(例如,如果结果直接作为参数传递给本身是通用的方法),则可能必须自己指定类型:
List<String> list = Arrays.asList(foo.<String>getResult(Something.class));
通用方法也可以使用它们在参数中声明的类型,这可以强制参数和结果类型达成一致:
public <T> T getResult(Class<T> type) { ... }
String string = foo.getResult(String.class); // ok
String string = foo.getResult(Something.class); // not ok
在运行时,泛型不存在,因此它只是尝试将结果分配给您尝试将其分配给的任何内容...如果它是错误的类型,则会得到ClassCastException
。
答案 1 :(得分:3)
VM在运行时很容易,因为T
由于type-erasure而只是Object
。换句话说:
return (T)getResult(annotated, new HashMap<String, Object>(0));
编译成与此相同的东西:
return (Object)getResult(annotated, new HashMap<String, Object>(0));
答案 2 :(得分:2)
该强制转换未经检查,这意味着未已检查 - 无论是在编译时还是在运行时。验证,编译和执行:
static <T> T magicCast(Class<T> clazz, Object o) {
return (T) o;
}
public static void main(String[] args) {
magicCast(Integer.class, "hello");
System.out.println("The magic cast always works.");
}
当然,这很危险。考虑:
public class Test<T> {
public final T foo;
public Test(Object foo) {
this.foo = (T) foo;
}
public static void main(String[] args) {
Test<String> test = new Test<String>(42);
// after being passed through dozens of methods
test.foo.startsWith("hello"); // ClassCastException
}
}
持有不是声明类型的子类型的对象的变量的歪曲称为堆污染。这就是为什么编译器被要求发出未经检查的警告的原因 - 除非有人压制了这个警告。
因此建议尽可能进行反射演员;例如:
static <T> T magicCast(Class<T> clazz, Object o) {
return clazz.cast(o); // reflective cast, checked at runtime
}
当然,如果你在编译时知道这个类,你应该使用普通的强制转换,因为这样可以让编译器执行额外的健全性检查,允许它拒绝像
这样的强制转换。int x = (Integer) "hello";
永远不会成功。
答案 3 :(得分:0)
不幸的是你没有写你如何调用这个方法。 我相信代码看起来像:
obj.getResult();
在这种情况下答案很简单:编译器将转换添加到MyClass,如果您反编译字节代码,您会看到类似
的内容(MyClass的)obj.getResult();
如果您调用方法并将结果分配给变量,则会发生同样的情况: MyClass结果= obj.getResult();
顺便说一下,我觉得很遗憾你添加了注释@SuppressWarining(“unchecked”) 如果T是“注释”类型,你应该说:
public T getResult(Class annotated){ return(T)getResult(带注释,新的HashMap(0)); }
这是使用泛型的常用方法。请参阅类Collections,Arrays,AbstractList.toArray()等。
答案 4 :(得分:0)
int y=10;
int z=12;