I was experimenting with Java Interfaces, and the following code gave an error.
In a class, a constructor takes Map as argument
public class ClassA{
private Map<String,InterfaceA> testMap;
ClassA(Map<String,InterfaceA> testMap){
this.testMap=testMap;
}
}
public class ClassB{
ClassA testA = new ClassA(new HashMap<String,ImplmntsInterfaceA>); //1st declaration
Map<String,ImplmntsInterfaceA> testMap=new HashMap<String,ImplmntsInterfaceA>(); //Second declaration
ClassA testB = new ClassA(testMap);
}
ImplmntsInterfaceA
is a class that implements InterfaceA
.
Both the ClassA
declarations are giving errors, first suggesting that Map constructor be changed to HashMap
and second asking to replace InterfaceA
generic to ImplmntsInterfaceA
.
Can someone help with why is it not working?
Thanks :)
I suspect you want to change Map<String,InterfaceA>
to Map<String, ? extends InterfaceA>
in the ClassA
constructor signature (and field). Otherwise a HashMap<String, ImplmntsInterfaceA>
really isn't a valid argument for it.
Consider what operations are valid on a Map<String,InterfaceA>
- you could write:
map.put("foo", new SomeArbitraryImplementationOfA());
That's not valid for a Map<String, ImplmntsInterfaceA>
as the value in the latter has to be a ImplmntsInterfaceA
. The compiler is protecting you from that.
If you use Map<String, ? extends InterfaceA>
, you won't be able to make any write operations within ClassA
(because you won't know what values are valid) but you'll be able to fetch from the map, knowing that every value at least implements InterfaceA
.
This is basically a more complicated version of why a List<Banana>
isn't a List<Fruit>
...
See more on this question at Stackoverflow