Jan*_*Jan 2 java oop generics wildcard subtyping
我试图理解 Java 中的泛型,但遇到了一些问题。这是我写的代码:
class Superclass{
}
class Subclass extends Superclass{
}
class Container <T>{
T elem;
}
public class Test {
public static void main(String[] args) {
Container<? extends Superclass> b = new Container<Superclass>();
b.elem = new Superclass();
}
}
Run Code Online (Sandbox Code Playgroud)
这个结果是一个奇怪的异常,我无法理解:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Type mismatch: cannot convert from Superclass to capture#1-of ?
at Test.main(Test.java:4)
Run Code Online (Sandbox Code Playgroud)
我尝试做出一些改变。如果我将注释行替换为:
Container<Superclass> b = new Container<Superclass>();
Run Code Online (Sandbox Code Playgroud)
一切正常。这对我来说很有意义。这只是普通的泛型,没有任何通配符。
然后我再次更改为注释行:
Container<?> b = new Container<Superclass>();
Run Code Online (Sandbox Code Playgroud)
我很惊讶这也导致了异常。然而我发现即使使用通配符,Java 也能保证类型安全。我想我明白为什么这会导致异常。
但我就是不明白为什么
Container<? extends Superclass> b = new Container<Superclass>();
Run Code Online (Sandbox Code Playgroud)
结果我出错了。据我所知,<? extends Superclass> 意味着我可以在容器中使用超类的任何子类型。在 Java 中,超类是其自身的子类型,或者至少具有像以前一样的功能。我认为通过使用 extends Superclass 会有类型安全并且 Java 会接受分配。
我尝试研究我的问题,但找不到任何令人满意的答案。如果有人可以帮助我,告诉我,我的错误是什么,并帮助我理解为什么这条线会导致问题,我将非常感激。
假设你写的是
Container<? extends Superclass> b = new Container<Subclass>();
// Clearly should compile, that's the whole point of ? extends
b.elem = new Superclass(); // SHOULD NOT compile
Run Code Online (Sandbox Code Playgroud)
第一行之后,b.elem有“真实类型” Subclass。您不能将 a 分配Superclass给 a Subclass,因此第二行不应编译。
您已明确告诉 Java 忘记 的“真实”类型参数b。众所周知,它是 的某个子类Superclass。但由于它可能是Subclass,并且不允许b.elem = new Superclass()编译,因此它拒绝编译它。
您只能以无论实际使用Container<? extends Superclass>哪个子类都有效的方式使用 a 。才不是。Superclass b.elem = new Superclass()
这是正常现象,也是意料之中的。