0

我想知道为什么以下通用定义不会产生编译器警告:

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
}

由于通用约束,不允许第一次调用callWildcard1to 。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 及其泛型时,我想哭……

4

1 回答 1

2

不同之处在于,当您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));
    }
}
于 2013-06-12T10:10:28.130 回答