使用 'super' 关键字限定泛型 [英] Bounding generics with 'super' keyword

查看:29
本文介绍了使用 'super' 关键字限定泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么我只能将 super 与通配符一起使用,而不能与类型参数一起使用?

Why can I use super only with wildcards and not with type parameters?

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

For example, in the Collection interface, why is the toArray method not written like this

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

推荐答案

super 绑定一个命名类型参数(例如 ),而不是通配符(例如 <? super T>)是 非法 仅仅是因为即使它被允许,它也不会做你希望它会做的事情,因为自从Object 是所有引用类型的终极super,一切都是Object实际上没有界限.

super to bound a named type parameter (e.g. <S super T>) as opposed to a wildcard (e.g. <? super T>) is ILLEGAL simply because even if it's allowed, it wouldn't do what you'd hoped it would do, because since Object is the ultimate super of all reference types, and everything is an Object, in effect there is no bound.

在您的具体示例中,由于 any 引用类型数组是 Object[](通过 Java 数组协方差),因此它可以用作 <代码>S[] toArray(S[] a) (如果这种绑定是合法的)在编译时,它不会在运行时阻止 ArrayStoreException.

In your specific example, since any array of reference type is an Object[] (by Java array covariance), it can therefore be used as an argument to <S super T> S[] toArray(S[] a) (if such bound is legal) at compile-time, and it wouldn't prevent ArrayStoreException at run-time.

你试图提出的是给定的:

What you're trying to propose is that given:

List<Integer> integerList;

并给定这个 假设 super 绑定在 toArray 上:

and given this hypothetical super bound on toArray:

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

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

the compiler should only allow the following to compile:

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

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

and no other array type arguments (since Integer only has those 3 types as super). That is, you're trying to prevent this from compiling:

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

因为,根据您的论点,String 不是 Integersuper.然而ObjectIntegersuperString[]是一个Object[],所以编译器仍然会让上面的代码编译,即使假设你可以做

because, by your argument, String is not a super of Integer. However, Object is a super of Integer, and a String[] is an Object[], so the compiler still would let the above compile, even if hypothetically you can do <S super T>!

所以下面的仍然可以编译(就像他们现在的方式一样),并且任何编译时检查都无法阻止运行时的ArrayStoreException使用泛型类型边界:

So the following would still compile (just as the way they are right now), and ArrayStoreException at run-time could not be prevented by any compile-time checking using generic type bounds:

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

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

Generics and arrays don't mix, and this is one of the many places where it shows.

再说一次,假设您有这个泛型方法声明:

Again, let's say that you have this generic method declaration:

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

你有这些变量声明:

Integer anInteger
Number aNumber
Object anObject
String aString

您对 (如果合法)的意图是它应该允许 add(anInteger)add(aNumber),当然还有 add(anObject),但不是 add(aString).好吧,String 是一个 Object,所以 add(aString) 仍然会编译.

Your intention with <T super Integer> (if it's legal) is that it should allow add(anInteger), and add(aNumber), and of course add(anObject), but NOT add(aString). Well, String is an Object, so add(aString) would still compile anyway.