显然,这个使用模板的特殊代码使 getFromSessionMap 的返回成为变量类型,因此不需要强制转换。
从根本上说,在获取结果session.getAttribute(sessionKey)
和分配给MyClassType
. Java 语言(和 JVM)不允许将某些不是MyClassType
实例(或其子类型)的对象分配给MyClassType
变量。
无论您如何编写代码,都必须进行类型转换。而且由于该属性(显然)不是 a 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
. 它必须。因为据它所知,它分配的实例可以是任何对象类型。
其他发帖人建议将 Class 参数添加到getFromSessionMap
. 就其本身而言,这完全没有任何作用。如果您还将方法的主体替换为:
return clazz.cast(session.getAttribute(sessionKey));
您将导致该方法实际进行真正的类型检查。但这只会导致ClassCastException
被扔到不同的地方。并且赋值语句仍然会进行隐藏类型转换!!