General Java Question

The following code compiles, but if I uncomment the commented line, it is not, and I am confused why. HashMap extends AbstractMap, and the first line in which the map is declared is compiled.

import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;

public class Test {

    public static void main(String args[]) {
        Map<String, ? extends AbstractMap<String, String>> map = new HashMap<String, HashMap<String, String>>();
        //map.put("one", new HashMap<String, String>());
    }
}

And I know the "right way":

import java.util.HashMap;
import java.util.Map;

public class Test {

    public static void main(String args[]) {
        Map<String, Map<String, String>> map = new HashMap<String, Map<String, String>>();
        map.put("one", new HashMap<String, String>());
    }
}
+3
source share
3 answers

The first code is unsafe - imagine that you are actually written:

HashMap<String, ConcurrentHashMap<String, String>> strongMap = 
    new HashMap<String, ConcurrentHashMap<String, String>>();
Map<String, ? extends AbstractMap<String, String>> map = strongMap;

Now:

map.put("one", new HashMap<String, String>());
ConcurrentHashMap<String, String> x = strongMap.get("one");

We must have ConcurrentHashMap, but in reality we have only HashMap.

Actually it’s much easier to explain if we reduce the number of generic files ... your script is really equivalent (say):

List<? extends Fruit> list = new List<Apple>();
list.add(new Apple());

which looks fine until you think it's equivalent to reality (as far as the compiler is concerned):

List<Apple> apples = new ArrayList<Apple>();
List<? extends Fruit> list = apples;
list.add(new Orange());
Apple apple = list.get(0); // Should be okay... but element 0 is an Orange!

, , . , .

+7

, . PECS, .

0

, , .

- . OO- .

, :)

.., (- - , ) , , , ( - , ), , , , Java- , generics Java (sementically -).

/ , /-.

:

List<Fruit> list = new ArrayList<Fruit>();

:

ConatainerType<ElementOfList> list = new MoreSpecificContainerType<ElementOfList>();

ElementOfList must perform both covariance and contravariance, since objects can be placed in (covariance) and received (contravariance), and this leaves only invariance, i.e. the same type / class.

It was a very long answer, but I hope this helps someone who asks a similar question in the future.

0
source

All Articles