为什么派生类有时只能在重写方法中使用特殊类型?

Dan*_*ski 2 java polymorphism

假设我有这个基类:

abstract public class Base {
    abstract public Map save();
    abstract public void load(Map data);
}
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,我可以在派生类中执行此操作:

public class Derived extends Base {
    @Override
    public Map<String, String> save() {    //Works
        ...
    }
    ...
}       
Run Code Online (Sandbox Code Playgroud)

但我不能这样做:

public class Derived extends Base {
    @Override
    public void load(Map<String, String> data) {    // Fails
        ...
    }
    ...
}       
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?为什么我可以使用专门的返回类型而不是专用的参数类型?

更令人困惑的是,如果我保留原始声明load,我可以将它分配给更特殊的类型:

public class Derived extends Base {
    @Override
    public void load(Map data) {
        Map<String, String> myData = data;   // Works without further casting
        ...
    }
    ...
}       
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 11

从专用类型到原始类型的隐式转换 - 总是"安全",因为使用原始类型的人不能做出任何假设.因此,有人希望Map从方法中获得原始数据并不介意他们是否得到了Map<String, String>.

没有从原始类型到专门类型的隐式转换-如果有人经过原料Mapload它可能有非字符串键和值.这完全合法的基本类型声明load.

抛弃泛型,你的方法有点像这样:

public abstract class Base
{
    public abstract Object save();
    public abstract void load(Object x);
}

public class Derived extends Base
{
    @Override
    public String save() { ... } // Valid

    @Override
    public void load(String x) // Not valid
}
Run Code Online (Sandbox Code Playgroud)

随着泛型被删除,为什么save这里的电话没问题是明确的,但load电话不是吗?考虑一下:

Base b = new Derived();
Object x = b.save(); // Fine - it might return a string
b.load (new Integer(0)); // Has to compile - but the override wouldn't work!
Run Code Online (Sandbox Code Playgroud)