我有简单的抽象结构
public abstract class Data<A extends Serializable> {
}
Run Code Online (Sandbox Code Playgroud)
然后这个类的String实现
public class StringData extends Data<String> {
}
Run Code Online (Sandbox Code Playgroud)
然后我有接口:
public interface Testicek<A extends Serializable> {
public abstract Data<A> test(Data<A> bla);
}
Run Code Online (Sandbox Code Playgroud)
现在我想创建实现此接口的类:
public class TesticekImpl implements Testicek<String> {
// OK
@Override
public StringData test(Data<String> bla) {
return null;
}
// compilation error
//@Override
//public StringData test(StringData bla) {
// return null;
//}
}
Run Code Online (Sandbox Code Playgroud)
为什么我不能将StringData类用作参数,并且只能在返回类型中使用?返回类型和参数的签名相同。
public interface Testicek<A extends Serializable> {
public abstract Data<A> test(Data<A> bla);
}
Run Code Online (Sandbox Code Playgroud)
Java允许协变返回类型,这意味着接口的实现可以比父接口返回更具体的类型,因为那些更具体的类型仍然是不那么具体的类型的实例,因此符合接口的约定。
但是,您不能使用更具体的参数类型,因为接口的约定表明它必须接受该类型的任何实例。
在里氏替换原则告诉我们,子类必须接受,没有更多的限制参数,并且必须返回没有更多的常规值。
Java不允许您使用“限制较少”的参数类型,因为Java 解析了在编译时要调用的方法的方式(这已经很复杂了)。从理论的角度来看,这是不必要的限制,但从实践的角度来看,则更为简单。
就您接受并返回相同类型而言:在接口中声明另一个类型变量:
public interface Testicek<A extends Serializable, D extends Data<A>> {
public abstract D test(D bla);
}
Run Code Online (Sandbox Code Playgroud)
然后,您的实现可以是:
public class TesticekImpl implements Testicek<String, StringData> {
@Override
public StringData test(StringData bla) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)