Nap*_*Nap 1 java templates classcastexception
我想知道如果将返回值设置为模板,模板变量的数据类型是什么.我在某个代码中看到过这个,但我不知道它从会话中检索到的值.
public class RequestObject {
public <T> T getFromSessionMap(String sessionKey) {
return (T)session.getAttribute(sessionKey);
}
}
Run Code Online (Sandbox Code Playgroud)
这个外部的代码是:
MyClassType type = request.getFromSessionMap("abc");
Run Code Online (Sandbox Code Playgroud)
在转换为我的对象时,该行遇到ClassCastException.但是当我添加监视session.getAttribute("abc")时,它显示该类型是MyClassType.任何帮助,将不胜感激.
显然,这个使用模板的特殊代码使得getFromSessionMap的返回变量类型,因此不需要强制转换.这适用于所有情况,但突然在代码的一部分失败了.
显然,这个使用模板的特殊代码使得getFromSessionMap的返回变量类型,因此不需要强制转换.
从根本上说,在得到结果和赋值之间必须有一个类型转换.Java语言(和JVM)将不允许将某个不是实例(或其子类型)的对象分配给变量.session.getAttribute(sessionKey)MyClassTypeMyClassTypeMyClassType
无论你如何编写代码,都必须进行类型转换.并且因为属性(显然)不是MyClassType(或子类型),所以你得到了一个ClassCastException.
所以真正的问题是为什么你没有得到编译错误?答案就是@SuppressWarnings("unchecked")!如果您删除了该警告,则会收到此行的"不安全类型转换"错误消息:
return (T) session.getAttribute(sessionKey);
Run Code Online (Sandbox Code Playgroud)
实际上,Java不能对通用类型进行(实际)类型转换.这就是警告/错误消息需要指出的内容.实际上,一旦代码编译完毕,这段代码
public <T> T getFromSessionMap(String sessionKey) {
return (T)session.getAttribute(sessionKey);
}
Run Code Online (Sandbox Code Playgroud)
实际上与此没有什么不同:
public Object getFromSessionMap(String sessionKey) {
return session.getAttribute(sessionKey);
}
Run Code Online (Sandbox Code Playgroud)
从技术上讲,这被称为"类型擦除".
那么类型检查/类型转换实际发生在哪里?答案就在这一行:
MyClassType type = request.getFromSessionMap("abc");
Run Code Online (Sandbox Code Playgroud)
即使你没有在这里编写类型转换,Java编译器生成的代码在分配值之前会进行类型转换type.它必须.因为据它所知,它所分配的实例可以是任何对象类型.
其他海报建议添加一个Class参数getFromSessionMap.这本身绝对没有任何意义.如果您还用以下方法替换方法的主体:
return clazz.cast(session.getAttribute(sessionKey));
Run Code Online (Sandbox Code Playgroud)
你将使该方法实际进行真正的类型检查.但这只会导致ClassCastException被扔在不同的地方.赋值语句仍将执行隐藏类型转换!!