Java 泛型和集合
我有一个关于 Java 泛型和集合的问题。像这样声明集合被认为是很好的做法:
List<String> catNames = new ArrayList<String>();
因为您可以更改 List
的类型,而不必担心破坏其余代码。但是当我尝试这样做时:
private static Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, ArrayList<Issue>>();
javac
抱怨
Type mismatch: cannot convert from HashMap<ResultsAggregator.IssueType,ArrayList<Issue>> to HashMap<ResultsAggregator.IssueType,List<Issue>>
而且,这是完全合法的:
private static Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, List<Issue>>();
这似乎更令人困惑,因为 List
是一个接口,而不是一个具体的类。这是怎么回事?这是类型擦除问题吗?
I have a question about Java Generics and Collections. It's considered good practice to declare a collection like this:
List<String> catNames = new ArrayList<String>();
because you can change the type of the List
and not worry about breaking the rest of your code. But when I try to do this:
private static Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, ArrayList<Issue>>();
javac
complains
Type mismatch: cannot convert from HashMap<ResultsAggregator.IssueType,ArrayList<Issue>> to HashMap<ResultsAggregator.IssueType,List<Issue>>
Moreover, this is perfectly legal:
private static Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, List<Issue>>();
which seems even more confusing, because List
is an interface, not a concrete class. What's going on here? Is this a type erasure issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果编译这样的代码是合法的,那么您将能够在
HashMap
中偷偷插入其他类型的元素:这不是您所期望的。
ArrayList
是一个List
,但这还不足以保证此代码的安全性和正确性。为了安全起见,它还要求List
为ArrayList
,这意味着泛型类型参数在这里不是协变的。您的最后一个代码是合法的,因为没有任何要求类型参数是具体类。同样,没有什么要求字段必须是抽象类型。
If it was legal to compile such a code, you would've been able to sneakily insert element of other types in the
HashMap
:which is not what you expect.
ArrayList<String>
is aList<String>
, but that's not enough for this code to be safe and correct. To be safe, it also requiresList<String>
to beArrayList<String>
, which means the generic type argument is not covariant here.Your last code is legal because nothing requires the type parameter to be a concrete class. Similarly, nothing requires a field to be of an abstract type.
没有理由在第二个示例中指定 ArrayList。它实际上并不创建列表,因此最好将界面放在那里。稍后您就可以调用以下内容了。
There is not reason to specify an ArrayList in your second example. It doesn't actually create a list so it is best to put the interface in there anyway. You will later then able able to call the following just fine.