通用定义内的原始类型

时间:2013-06-12 08:48:07

标签: java generics types raw-types subtyping

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

class MyClass<T extends List> { }

以及上述定义与

的不同之处
class MyClass<T extends List<?>> { }

每当您阅读有关泛型的内容时,您都会了解应该如何避免原始类型,因此,无论何时处理泛型类型,都会收到编译器警告。但是,第一个定义中的原始类型不会产生这样的警告。

其次,我想知道原始类型和泛型类型之间的确切子类型定义是怎样的。根据{{​​3}},原始类型是类型检查的“选择退出”类型,这样只要涉及原始类型,类型检查就会处于非活动状态。这个假设是否正确?这是如何影响上述“原始”通用定义的?

感谢您的帮助!

更新:我明白你在说什么。但是,这不是我所困惑的。看看这个场景:

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
}

由于通用约束,不允许从callWildcard1callBound1的第一次调用。然而,第二个是允许的。如何在没有“内部原始类型”的情况下执行第一次调用?我不明白为什么编译器会禁止第一个。 Shoul没有任何参数有效的通配符参数暗示? 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及其泛型时,我想哭...

1 个答案:

答案 0 :(得分: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));
    }
}