我想知道为什么以下通用定义不会产生编译器警告:
class MyClass<T extends List> { }
上面的定义有何不同
class MyClass<T extends List<?>> { }
每当您阅读有关泛型的内容时,您都会了解应如何避免原始类型,因此,每当您处理泛型类型时,您都会收到编译器警告。然而,第一个定义中的原始类型不会产生这样的警告。
其次,我想知道原始类型和泛型类型之间的确切子类型定义如何。根据this summary ,原始类型是类型检查的“选择退出”,因此只要涉及原始类型,类型检查就处于不活动状态。这个假设正确吗?这对上述“原始”通用定义有何影响?
感谢您的帮助!
更新:我明白你在说什么。然而,这并不是我困惑的地方。看看这个场景:
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
至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 及其泛型时,我想哭......
最佳答案
不同之处在于,当您使用 class MyClass<T extends List> { }
时里面MyClass
你失去了类型安全。
例如:
class A <T extends List<?>>{
void someFunc(T t) {
t.add(new Object());//compilation error
}
}
class B <T extends List>{
void someFunc(T t) {
//compiles fine
t.add(new Object());
t.add("string");
t.add(new Integer(3));
}
}
关于java - 泛型定义内的原始类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17061292/