我想知道为什么以下通用定义不会产生编译器警告:
class MyClass<T extends List> { }
以及上述定义与
class MyClass<T extends List<?>> { }
每当您阅读泛型时,您就会了解如何避免使用原始类型,因此,每当您处理泛型类型时,都会收到编译器警告。然而,第一个定义中的原始类型不会产生这样的警告。
其次,我想知道原始类型和泛型类型之间的确切子类型定义是怎样的。根据此摘要,原始类型是类型检查的一种“选择退出”,因此只要涉及原始类型,类型检查就只是不活动的。这个假设正确吗?这对上述“原始”通用定义有何影响?
感谢您的帮助!
更新:我明白你在说什么。然而,这不是我感到困惑的。看看这个场景:
class MyClass<T extends MyClass<T>> {}
public void callWildcard1(MyClass<?> node) {
callBound1(node);
}
public <T extends MyClass<T>> void callBound1(T node) {
// Do something
}
public void callWildcard2(MyClass<?> node) {
callBound2(node);
}
public <T extends MyClass> void callBound2(T node) {
// Do something
}
由于通用约束,不允许第一次调用callWildcard1
to 。callBound1
然而,第二个是允许的。如何在没有“内部原始类型”的情况下执行第一次调用?我不明白为什么编译器会禁止第一个。不应该有任何参数有效的通配符参数暗示? extends MyClass<?>
吗?
更新2:我通过反复试验发现,我可以通过定义来解决问题:
public <T extends MyClass<? extends T> void callBound2(T node) {
// Do something
}
尽管我不太明白为什么。但是,在查看此示例时,还有更多的困惑:(这是我实际尝试做的一个非常简单的版本。)
public void call() {
genericCall1(new MyFilter<MyClass<?>>(), MyClass.class);
genericCall2(new MyFilter<MyClass<?>>(), MyClass.class);
}
public <T extends MyClass<? extends T>> void genericCall1(MyFilter<T> filter, Class<? extends T> filterBoundary) {
// Do something.
}
public <T extends MyClass<? extends T>, U extends T> void genericCall2(MyFilter<T> filter, Class<? extends U> filterBoundary) {
// Do something.
}
class MyClass<T extends MyClass<T>> { }
class MyFilter<T extends MyClass<? extends T>> { }
为什么被genericCall1
禁止而不被禁止genericCall2
?同样,我通过学术猜测而不是真正的理解找到了解决方案。有时,在使用 Java 及其泛型时,我想哭……