不好意思,如果我以前曾问过这个问题(我几乎可以肯定),但是我找不到正确的关键词或从一堆无关的泛型问题中找出答案。
这有效:
vector-of
那为什么会出现编译器错误?
Object a = null;
Set<Object> b = (Set<Object>)a;
为什么这个简单的解决方法有效?
Set<Object> c = null;
Set<Set<Object>> d = (Set<Set<Object>>)c;
我有一个库方法,该方法返回经过预处理的JSON消息的Set<Object> e = null;
Set<?> f = (Set<?>)e;
Set<Set<Object>> g = (Set<Set<Object>>)f;
。进行手动深度类型检查后,我需要进行强制转换并将其返回为Map<Number, Object>
,期望出现未经检查的强制转换警告,由于我刚刚对其进行了检查,因此我可以忽略该警告。
但是我遇到了编译器错误:
Map<Number, Map<String, Map<String, Object>>>
或以更具可读性的形式(基于IDE中的错误):
Error:(61, 10) java: Cannot cast from java.util.Map<java.lang.Number,java.lang.Object> to java.util.Map<java.lang.Number,java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Object>>>
)
[edit] 从操作方法问题更改为为什么问题。
答案 0 :(得分:1)
请注意,由于泛型类型是在运行时删除的,因此在进行这些强制类型转换时实际上并没有发生实质性的变化。的确归结为“编译器允许这样做吗?”
泛型的目的之一是确保类型安全。如果由于某种原因可以将List<List<Object>>
分配给List<Object>
,则会丢失类型安全性:
List<List<Object>> listOfLists = new ArrayList<>();
List<Object> list = listOfLists; // suppose this is valid
list.add(new Object());
listOfLists.get(0); // what happens here?
(为方便起见,我在这里使用列表。您可以轻松地将其应用于地图或集合或任何其他通用类型)
listOfLists.get(0)
将返回Object
的实例,因为这是我们添加的内容,但是不会!因为它的类型是List<List<Object>>
!这就是为什么像这样进行投射会破坏类型安全性的原因。
但是,以下两个强制转换是有效的:
List<Object> e = null;
List<?> f = (List<?>)e;
List<List<Object>> g = (List<List<Object>>)f;
List<?> f
的意思是“ f
是扩展Object
的某个类的列表,但该类可以是任何东西”。请注意,List<?>
与List<Object>
不同。您不能做f.add("String")
,因为?
不一定是String
,对吗?
由于多数人(不正确地)认为可以将List<String>
分配给List<Object>
的相同原因而允许进行第一次强制转换。实际上,不需要此强制转换。 List<String>
是对List
进行扩展的 Object
。
第二种转换是告诉编译器您知道?
是什么,它就是List<Object>
。编译器通过发出未经检查的警告来警告您?
可能是错误的。
从某种意义上讲,您是在问为什么不能直接从Integer
投射到String
,但是可以先从Integer
投射到Object
,然后再投射到String
。
我觉得您的困惑可能是由于对<Object>
和<?>
之间的差异的误解引起的。 This post可能值得一读。
答案 1 :(得分:0)
这是因为泛型不支持子类型。以下代码也无法编译。
List<Number> numbers = new ArrayList<Integer>();
尽管Number
是Integer
的超类型,ArrayList<Number>
不是ArrayList<Integer>
的超类型。这些是完全不同的类型。
在您的情况下,您尝试将Object
替换为Set<Object>