Java泛型和集合

Ami*_*ani 4 java generics collections

我有一个关于Java Generics和Collections的问题.声明像这样的集合被认为是一种好习惯:

List<String> catNames = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

因为你可以改变它的类型,List而不用担心破坏你的其余代码.但是当我尝试这样做时:

private static Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, ArrayList<Issue>>();
Run Code Online (Sandbox Code Playgroud)

javac 抱怨

Type mismatch: cannot convert from HashMap<ResultsAggregator.IssueType,ArrayList<Issue>> to HashMap<ResultsAggregator.IssueType,List<Issue>>
Run Code Online (Sandbox Code Playgroud)

而且,这是完全合法的:

private static Map<IssueType, List<Issue>> orphanedAttrMap = new HashMap<IssueType, List<Issue>>();
Run Code Online (Sandbox Code Playgroud)

这似乎更令人困惑,因为它List是一个接口,而不是一个具体的类.这里发生了什么?这是一种类型擦除问题吗?

Meh*_*ari 8

如果编译这样的代码是合法的,那么你就可以偷偷地在其中插入其他类型的元素HashMap:

HashMap<IssueType, List<Issue>> a = new HashMap<IssueType, ArrayList<Issue>>();
a.put(someIssue, new SomeClassThatImplementsListOfIssueButIsNotArrayList());
Run Code Online (Sandbox Code Playgroud)

这不是你所期望的.ArrayList<String>是一个List<String>,但这还不足以使这段代码安全无误.为了安全起见,也要求List<String>ArrayList<String>,这意味着泛型类型参数不协变这里.

您的上一个代码是合法的,因为没有必要将type参数作为具体类.同样,没有什么要求字段是抽象类型.