Can a java constructor have interfaces as arguments

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 :)

Jon Skeet
people
quotationmark

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>...

people

See more on this question at Stackoverflow