5

假设我有这个:

class Base<T> {}

class Derived<T> extends Base<T> {}

然后在我的代码中,我可以安全地投射而不会发出这样的警告:

public <T> void foo(Base<T> base) {
    Derived<T> f = (Derived<T>) base; // fine, no warning
}

这很好。但是如果派生类有更多的类型参数,它就不再起作用了:

class Base<T> {}

class Derived<T, U> extends Base<T> {}

public <T> void foo(Base<T> base) {
    Derived<T, ?> f = (Derived<T, ?>) base; // unchecked warning!
}

这是为什么?我在这里有什么明显的遗漏吗?

4

1 回答 1

5

这对我来说似乎是一个错误。来自JLS §5.5.2。检查演员表和未检查演员表

从类型 S 到参数化类型(第 4.5 节)的强制转换是未经检查的,除非至少满足以下条件之一:

  • 小号<:T

  • T 的所有类型参数(第 4.5.1 节)都是无界通配符

  • T <: S 和 S 除了 T 之外没有子类型 X,其中 X 的类型参数不包含在 T 的类型参数中。

鉴于您的类型Base<T>Derived<T, ?>asST分别,前两个条件显然不成立。

这就留下了第三个条件——如果我们可以识别出一个子类型,Base<T>而不是Derived<T, ?>其类型参数不包含在Derived<T, ?>. 如果警告是正确的,则必须存在这样的子类型,但我无法识别。例如,Derived<?, ?>不起作用,因为它不是Base<T>.

于 2013-07-26T14:58:53.820 回答