gpt4 book ai didi

java - Java泛型参数如何在被重写的方法中工作?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:04:09 29 4
gpt4 key购买 nike

我有两个类(class),

A.java

public abstract class A {
@Override
public abstract <T extends A> T add();

@Override
public abstract <T extends A> T addWithParam(T param);
}

B.java

public class B extends A {
@Override
public B add() {...}

@Override
public B addWithParam(B param) {...}
}

add() 方法可以编译,但是 addWithParam 会产生错误,指出 addWithParam(B) 必须重写其中一个较高类(A 中的方法)这种情况)。一个修复方法是完全丢失覆盖注释,但我的意图是强制用户覆盖 B 类中的方法并返回类型 B 的对象。

我只能想到两种方法来解决这个问题。第一个解决方案是将返回类型从泛型 T 设置为 A。这将允许我返回类型 A,但是用户随后必须将 B.addWithParam(B) 的返回结果转换为类型 B,这就是我'试图避免。

另一种解决方案是将抽象方法的可见性从 public 更改为 protected(在 A.java 中)。在我将返回类型更改为 A 的前面提到的解决方案中,A 的继承类创建了一个返回 (B) B.addWithParam(B param)(记住 B.addWithParam(B param) 返回父类(super class)指定的类型 A)。

那么这里的问题是,为什么会产生原来的错误呢?是我的代码写错了,还是 Java 直接不支持我想要实现的目标?

最佳答案

public abstract <T extends A> T add();

这个方法声明的意思是对于任何对象a类型 A或子类型,您可以调用方法 a.add()并取回 A 的任何子类型来电者想要。所以如果你有 class B extends Aclass C extends A ,您刚才告诉 Java 的是以下内容应该有效:

C c = myB.add();

你不是这个意思。相信我。

public abstract A add();

表示调用 add()在任何 A至少会给你一个A返回,以及 A 的子类型可以更详细地指定他们返回的确切类型,所以你可以写

class B extends A {
public B add() { ... }
}

这样比较合理。这让你做的是指定 addWithParam方法将只接受 B , 而不是另一个 A类型。

没有任何方法可以强制子类返回它自己类型的实例。人们使用各种技巧和提示来实现不同程度的有效性,例如:

class A<T extends A> {
abstract T add();
abstract T addWithParam(T t);
}
class B extends A<B> {
B add() { ... }
B addWithParam(B b) { ... }
}

这至少可以完成您想要做的事情。它不会做的是阻止某人写 class C extends A<B> .

关于java - Java泛型参数如何在被重写的方法中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42288698/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com