我有以下代码:
public class Foo {
interface Coo<T> {
public T cool();
}
abstract class Bar<T extends Bar<T>> implements Coo<T> {
@SuppressWarnings("unchecked")
T doSomething() {
return (T) this;
}
@SuppressWarnings("unchecked")
@Override
public T cool() {
return (T) this;
}
}
class FooBar extends Bar<FooBar> {
@Override
public FooBar cool() {
return super.cool();
}
}
}
为什么转换为(this)对象类型不安全?当Bar实现Coo时,返回cool的通用说法不一定是T类型,它会扩展Bar或它的子类吗?
答案 0 :(得分:3)
由于this
中的Bar
具有Bar<T extends Bar<T>>
类型而非T
,因此编译器会为Bar#doSomething
生成警告。以下内容不会产生任何警告:
abstract class Bar<T extends Bar<T>> {
Bar<T> doSomething() {
return this;
}
}
Bar#cool
的正文期望this
成为T
的子类型,而不是Bar#cool
。在this
中,Bar<T extends Bar<T>>
的类型为Coo<T>
,其子类型为T
,但不是{{1}}。
答案 1 :(得分:1)
T
扩展了Bar<T>
,但Bar<T>
(this
的类型)未扩展T
。
想象
class A extends Bar<A> { ... }
class B extends Bar<A> { ... }
然后该方法继承为:
class B {
A doSomething() {
return (A) this;
}
}
这显然是不对的。
使用泛型无法做到你想要的。这是人们的一个很大的误解。他们认为递归边界将允许你做自我类型。但是递归边界在Java中几乎没有用。在您看到人们写interface Bar<T extends Bar<T>>
的地方中,有99%的地方将其写为interface Bar<T>
一样好。