Java 泛型和集合

发布于 2024-10-08 09:04:04 字数 813 浏览 2 评论 0原文

我有一个关于 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

海之角 2024-10-15 09:04:04

如果编译这样的代码是合法的,那么您将能够在 HashMap 中偷偷插入其他类型的元素:

HashMap<IssueType, List<Issue>> a = new HashMap<IssueType, ArrayList<Issue>>();
a.put(someIssue, new SomeClassThatImplementsListOfIssueButIsNotArrayList());

这不是您所期望的。 ArrayList 是一个 List,但这还不足以保证此代码的安全性和正确性。为了安全起见,它还要求 ListArrayList,这意味着泛型类型参数在这里不是协变的。

您的最后一个代码是合法的,因为没有任何要求类型参数是具体类。同样,没有什么要求字段必须是抽象类型。

If it was legal to compile such a code, you would've been able to sneakily insert element of other types in the HashMap:

HashMap<IssueType, List<Issue>> a = new HashMap<IssueType, ArrayList<Issue>>();
a.put(someIssue, new SomeClassThatImplementsListOfIssueButIsNotArrayList());

which is not what you expect. ArrayList<String> is a List<String>, but that's not enough for this code to be safe and correct. To be safe, it also requires List<String> to be ArrayList<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.

把回忆走一遍 2024-10-15 09:04:04

没有理由在第二个示例中指定 ArrayList。它实际上并不创建列表,因此最好将界面放在那里。稍后您就可以调用以下内容了。

Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, List<Issue>>();

orphanedAttrMap.put(IssueType.TYPE, new ArrayList<Issue>());

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.

Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, List<Issue>>();

orphanedAttrMap.put(IssueType.TYPE, new ArrayList<Issue>());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文