为什么 Map<String, Object> 不等于 Map<String, ?>

fas*_*ava 3 java generics dictionary

我在第二行收到错误,不是所有项目都是一个吗Object

Map<String, ?> value;  // I get value from some place
Map<String, Object> val = value;
Run Code Online (Sandbox Code Playgroud)

Mic*_*rry 5

泛型?(在 Java 领域)中的 表示它可以替换为任何类型(该类型可以选择有界)。在泛型的情况下,Object 不能安全地以这种方式替换任何类型(它遇到了泛型和泛型的问题)子类型化,因为泛型在运行时被删除。)

因此,两者在语义上并不像您首先期望的那样相同,因此会出现编译错误。

作为如果允许这样做可能会出现问题的示例,您可以这样做:

Map<String, ?> value = new HashMap<String, String>();
Map<String, Object> val = value; //This line would fail in real life, but assuming it passes...
val.put("Hello", 0); //We could do this!
Run Code Online (Sandbox Code Playgroud)

...这显然没有任何意义 - 是HashMap类型<String, String>,但你已经在Integer其中放入了!

这就是?表示方式不同的地方 - 您不能Object在映射中放置除 an 之外的任何内容而不导致编译错误:

value.put("Hello", 0); //Error
Run Code Online (Sandbox Code Playgroud)

值得注意的是,数组不具有这些相同的限制,因为它们具体化的,因此当发生类型不匹配时可以在运行时抛出有意义的异常。(这是否更可取是一个有争议的问题,但我个人更喜欢在编译时尽早捕获错误!)由于泛型不能做到这一点,编译器必须确保它们在编译时的安全。

  • 很好的解释,除了旧的误解,即泛型由于类型擦除而不是协变的 - 编译时检查总是比运行时检查更可取。 (2认同)