关于java:使用’super’关键字绑定泛型

Bounding generics with 'super' keyword

为什么我只能对通配符使用super,而不能对类型参数使用EDOCX1?

例如,在Collection接口中,为什么toArray方法不是这样写的?

1
2
3
interface Collection<T>{
    <S super T> S[] toArray(S[] a);
}


super绑定一个命名的类型参数(例如而不是通配符(例如是非法的,因为即使允许,它也不会像您希望的那样做,因为由于Object是所有引用类型的最终super并且所有内容都是Object实际上没有bou钕

在您的具体示例中,由于任何引用类型的数组都是EDCOX1×6(由Java数组协方差),因此它可以在编译时用作EDCOX1×7(如果这种绑定是合法的)的参数,并且它不会在运行时阻止EDCOX1×8的引用。

你想提出的建议是:

1
List<Integer> integerList;

假设supertoArray绑定:

1
<S super T> S[] toArray(S[] a) // hypothetical! currently illegal in Java

编译器只允许编译以下内容:

1
2
3
integerList.toArray(new Integer[0]) // works fine!
integerList.toArray(new Number[0])  // works fine!
integerList.toArray(new Object[0])  // works fine!

而且没有其他数组类型参数(因为Integer只有这3种类型,即super)。也就是说,您试图阻止编译:

1
integerList.toArray(new String[0])  // trying to prevent this from compiling

因为,根据你的论点,String不是Integersuper。但是,ObjectIntegersuperString[]Object[]的,所以即使假设你可以执行编译,编译器还是会让上面的编译!

因此,以下仍然可以编译(就像现在一样),运行时的ArrayStoreException不能被任何使用泛型类型边界的编译时检查所阻止:

1
2
integerList.toArray(new String[0])  // compiles fine!
// throws ArrayStoreException at run-time

泛型和数组不混合,这是它显示的众多地方之一。

非数组示例

同样,假设您有这个泛型方法声明:

1
<T super Integer> void add(T number) // hypothetical! currently illegal in Java

您有这些变量声明:

1
2
3
4
Integer anInteger
Number aNumber
Object anObject
String aString

你对的意图(如果合法)是允许add(anInteger)add(aNumber),当然是add(anObject)而不是add(aString)。好吧,StringObject,所以add(aString)仍然可以编译。

也见

  • Java教程/泛型
    • 子类型
    • 野猫游戏更有趣

相关问题

关于泛型类型规则:

  • 有什么简单的方法来解释为什么我不能做List animals = new ArrayList()
  • Java泛型(非)协方差
  • 什么是原始类型,为什么不使用它?
    • 解释原始类型ListList的区别,后者与List不同。

      使用superextends时:

      • Java Generics: What is PECS?
        • 从有效的Java第二版:"生产者EDCOX1,36,消费者EDCOX1,0"
      • 在Java泛型中EDCOX1与0和EDCX1 36的区别是什么?
      • 有什么区别?
      • 如何添加到List数据结构中?(你不能!)