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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With