考虑这个抽象类
abstract class AbstractBox {
abstract Object getContent();
}
现在我实现了StringBox
,但可能还有其他Box
es实现会返回任何类型的内容,这使我无法使抽象方法的返回类型更具体:< / p>
class StringBox extends AbstractBox {
@Override
Object getContent() {
return "";
}
}
而不是让getContent()
声明它会返回Object
,很明显它会返回String
,我也可以
class StringBox extends AbstractBox {
@Override
String getContent() {
return "";
}
}
因此清楚地说明了getContent()
将返回的内容并仍然覆盖抽象方法。
答案 0 :(得分:4)
覆盖允许指定协变返回类型,在这里您可以在StringBox
子类中使用它。
自Java 1.5起,此功能可用 来自JLS.Chapter 8. Classes(强调是我的):
<强> 8.4.5。方法结果
...
如果相反,则返回类型可能会因为相互覆盖的方法而异 返回类型是引用类型。 的概念 return-type-substitutability支持协变返回,即 将返回类型专门化为子类型。
实际上,如果你使用StringBox
声明的类型操作变量,那么类的客户端可以返回更具体的类型,这是一件好事,因为它可以避免向下转换。
例如:
StringBox box = new StringBox();
String boxContent = box.getContent();
但是如果你使用AbstractBox
声明的类型操作变量,它在编译时或运行时没有任何副作用,因为客户端期望仍然有Object
作为返回类型:
AbstractBox box = new StringBox();
Object boxContent = box.getContent();
一般来说,使用协方差返回应该使用它,如果它使客户端代码更清晰和更简单(没有任何强制转换)。
答案 1 :(得分:2)
是的,它是“协变返回类型”。
编译器仍然为Object
生成一个“桥接方法”,返回StringBox
,因此代码大小略有增加(并且可能会降低性能,但这应该很容易被JIT淘汰。
正如@khelwood所提到的,你经常想要使用泛型而不是协变返回类型(或者除此之外)。
答案 2 :(得分:0)
我确实认为这不是问题。如果您使用抽象类,例如,如果您有
AbstractBox box;
box.getContent()
您将获得一个对象,如果您了解实现,则可以进行投射
如果您使用具体实现,您将获得String(也是一个对象)。
另一个解决方案是使用泛型方法,例如:
abstract class AbstractBox<T> {
abstract T getContent();
}
并在实现中将其添加为String
class StringBox extends AbstractBox<String> {
@Override
String getContent() {
return "";
}
}
我不认为它有很大的不同,因为你仍然必须使用StringBox来了解实现