我在第二行收到错误,并非所有项目都是Object
?
Map<String, ?> value; // I get value from some place
Map<String, Object> val = value;
答案 0 :(得分:4)
泛型中的?
(在Java土地中)表示它可以替换任何类型(此类型可以选择有界。)对于泛型,Object
不能< / em>以这种方式安全地替换任何类型(它会遇到generics and subtyping的问题,因为泛型会在运行时被删除。)
因此,这两者在语义上并不像您最初预期的那样相同,因此编译错误。
如果允许这样做可能会出错,可以这样做:
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!
...显然没有任何意义 - HashMap
属于<String, String>
类型,但您已在其中添加了Integer
!
这是?
表示不同的地方 - 你不能在地图中放置Object
以外的任何内容而不会导致编译错误:
value.put("Hello", 0); //Error
值得注意的是,数组不具有这些相同的限制,因为它们被实现了,因此在发生类型不匹配时可以在运行时抛出有意义的异常。 (这是否更可取是一个争论的问题,但我个人更喜欢在编译时尽早发现错误!)由于泛型不能这样做,编译器必须确保它们在编译时的安全性。
答案 1 :(得分:1)
我是个白痴,为了我的耻辱而离开这里。
Covariance and contravariance with generic types in c#是混淆的常见原因。它在.NET 4中是有点固定的(不是它本身就被破坏了),但制作泛型类型的新方法是按照你所描述的方式工作,而不是追溯。
答案 2 :(得分:0)
没有。 Map<String, Object>
不是Map<String, ?>
的超类型,因此分配不是类型安全的。
(但是,Map<String, ?>
是所有Map<String, T>
的超类型。因此,代码的反面将起作用。)
答案 3 :(得分:0)
Map<String, ?>
和Map<String, Object>
都可以将Object
作为值。据您所知,在您的代码中,您可以假设最具体。 (与.get(key)
相关)
但占位符?
意味着它可以是不同的具体类型。
E.g。 Map<String, ?>
在运行时允许为Map<String, Apple>
。并且您不能将具有不同类型的泛型分配给彼此。即使只有理论上有机会你可以拥有苹果地图。
答案 4 :(得分:0)
不,它是capture of
并导致编译错误,因为显然?
并不仅仅意味着对象......但是,这就是你想要的 -
Map<String, Object> value; // I get an Object
Map<String, ? extends Object> val = value; // Something that is an Object.
甚至
Map<String, Object> value;
Map<String, ?> val = value; // Will take anything...
// Object is more specific.
答案 5 :(得分:0)
使用通配符绑定?
,您告诉编译器您不知道并且不关心泛型类型是什么。如果您只是从容器中读取并使用在上限上声明的方法(例如,您可以从Collection<?>
读取并调用toString()
或List<? extends Closeable>
并且调用close()
),但是将对象放入集合中是不安全的(它可能真的是Collection<URL>
,并且尝试添加String
会破坏它。)
答案 6 :(得分:-2)
Map<String, ?> value = null; // initialize
Map<String, Object> val = (Map<String, Object>) value; //cast