Let’s say I have this base class:
abstract public class Base { abstract public Map save(); abstract public void load(Map data); }
to my surprise I could do this in a derived class:
public class Derived extends Base { @Override public Map<String, String> save() { //Works ... } ... }
but I couldn’t do this:
public class Derived extends Base { @Override public void load(Map<String, String> data) { // Fails ... } ... }
What is happening here? Why can I use a specialized return type but not a specialized parameter type?
What’s even more confusing is that if I keep the original declaration of load, I can just assign it to the more special type:
public class Derived extends Base { @Override public void load(Map data) { Map<String, String> myData = data; // Works without further casting ... } ... }
There’s an implicit conversion from the specialized type to the raw type – that’s always ‘safe’ because someone using the raw type can’t make any assumptions. So someone expecting to get a raw
Mapback from a method doesn’t mind if they get aMap<String, String>.There isn’t an implicit conversion from the raw type to the specialized type – if someone passes a raw
Mapintoloadit may have non-string keys and values. That’s completely legal by the base type declaration ofload.Leaving generics aside, your methods are a bit like this:
With the generics removed, is it clear why the
savecall is okay here, but theloadcall isn’t? Consider this: