如果将返回值设置为模板,我想知道模板变量的数据类型是什么。我已经在某个代码中看到了这个,但我不知道它从会话中检索到的值。
public class RequestObject {
public <T> T getFromSessionMap(String sessionKey) {
return (T)session.getAttribute(sessionKey);
}
}
外面的代码是:
MyClassType type = request.getFromSessionMap("abc");
在转换为我的对象时,该行遇到ClassCastException。但是当我添加监视session.getAttribute(“abc”)时,它显示该类型是MyClassType。任何帮助将不胜感激。
显然这个使用模板的特殊代码使得getFromSessionMap的返回变量类型,因此不需要强制转换。这适用于所有情况,但突然在代码的一部分失败了。
答案 0 :(得分:6)
显然这是使用的特殊代码 模板让回归 getFromSessionMap是一个变量类型和 因此无需演员。
从根本上说,必须在获取session.getAttribute(sessionKey)
的结果和MyClassType
的分配之间的某种类型。 Java语言(和JVM)将不允许某个不是MyClassType
实例(或其子类型)的对象分配给MyClassType
变量。
无论您如何编写代码,都必须进行类型转换。由于属性(显然)不是MyClassType
(或子类型),因此您获得了ClassCastException
。
所以真正的问题是为什么你没有得到编译错误?答案是@SuppressWarnings("unchecked")
!如果您删除了该警告,则会收到此行的“不安全类型转换”错误消息:
return (T) session.getAttribute(sessionKey);
实际上,Java不能对通用类型进行(实际)类型转换。这就是警告/错误消息需要指出的内容。实际上,一旦代码编译完毕,这段代码
public <T> T getFromSessionMap(String sessionKey) {
return (T)session.getAttribute(sessionKey);
}
实际上与此没有什么不同:
public Object getFromSessionMap(String sessionKey) {
return session.getAttribute(sessionKey);
}
从技术上讲,这被称为“类型擦除”。
那么类型检查/类型转换实际发生在哪里?答案就在这一行:
MyClassType type = request.getFromSessionMap("abc");
即使你没有在这里编写类型转换,Java编译器生成的代码在将值赋给type
之前会进行类型转换。它必须。因为据它所知,它所分配的实例可能是任何对象类型。
其他海报建议在getFromSessionMap
中添加一个Class参数。这本身就没有绝对没有。如果您还用以下方法替换方法的主体:
return clazz.cast(session.getAttribute(sessionKey));
您将使该方法实际进行真正的类型检查。但这只会导致ClassCastException
被抛到不同的地方。赋值语句仍将执行隐藏类型转换!!
答案 1 :(得分:0)
在问题的示例中,返回类型为T
。被删除的类型将Object
隐含地T extends Object
。实际的强制转换是在调用方法的字节码中执行的(您可以使用javap -c
来查看)。
通常,您应该在会话中保持“顶级”对象的数量尽可能小。这样做的好处之一是,不再需要像这样的hacky方法。
答案 2 :(得分:0)
任何帮助都会受到赞赏,因为我的代码遇到了ClassCastException。
如果你得到的是ClassCastException
,那就意味着你正试图将某些东西投射到某些东西上,就像在下面的代码中一样:
Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date
ClassCastException
应该有一个启发性的详细信息,例如“java.lang.String不能转换为java.util.Date”。
答案 3 :(得分:0)
您在方法体中使用了类型转换('(T)session.getAttribute(sessionKey)')。
这意味着您明确地告诉编译器'我绝对确定返回的对象IS-A T并准备好处理错误,如果它不是'。
此处您对属性类型的假设不正确,并且您收到了错误消息。所以,一切都是正确的,运行时已经为您提供了不是 IS-A MyClassType的真实属性对象类型。