简体   繁体   中英

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

I suspect you want to change Map<String,InterfaceA> to Map<String, ? extends InterfaceA> 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> 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> ...

Please take a look at your ClassA constructor.

ClassA(Map<String,InterfaceA> testMap){ // *
  this.testMap=testMap;
}

Now your construcotr(*) will accept Map<String, InterfaceA> type or Map<String,InterfaceA> implementation. Eg: HashMap<String, InterfaceA> .

You can change your constructor to following to accept HashMap<String,ImplmntsInterfaceA>

Eg:

ClassA(Map<String,? extends InterfaceA> testMap){ 
  this.testMap=testMap;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM