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

问题描述

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

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

 界面集合< T> {
< S super T> S [] toArray(S [] a);


解决方案

super 来绑定一个命名的类型参数(例如< S super T> ),而不是通配符(例如< ;?super T> )是 ILLEGAL ,因为即使允许,它也不会做你希望它做的事情,因为 Object 是所有引用类型的最终 super ,并且所有内容都是 Object 实际上是没有界限的。



在具体的例子中,因为任何引用类型的数组都是一个 Object [] (通过Java数组协变),因此它可以用作< S super T>的参数。在编译时,S [] toArray(S [] a)(如果这样的绑定是合法的),并且它不会阻止 ArrayStoreException




$ b

您试图建议的是: C $ C>列表与LT;整数> integerList;

并给出这个假设 super 绑定在 toArray

 < S super T> ; S [] toArray(S [] a)//假设!目前在Java中是非法的

编译器应该只允许编译以下代码:

  integerList.toArray(new Integer [0])//正常工作! 
integerList.toArray(new Number [0])//正常工作!
integerList.toArray(new Object [0])//正常工作!

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

  integerList.toArray(new String [0])//尝试以防止编译

,因为您的论点 String 不是超级整数 Object super 整数,并且一个 String [] 是一个 Object [] ,所以编译器仍然即使假设你可以做< S super T>



所以下面的仍然会被编译(就像它们现在的样子),并且在运行时 c $ c> ArrayStoreException 不能被任何编译阻止使用泛型类型边界检查时间:

  integerList.toArray(new String [0])//编译得很好! 
//在运行时抛出ArrayStoreException

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






非数组示例



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

 < T super Integer> void add(T number)//假设!目前在Java中是非法的

你有这些变量声明:

 整数anInteger 
数字a数字
对象anObject
字符串aString

您打算使用< T super Integer> (如果它是合法的),它应该允许 add(anInteger) add(aNumber),当然 add(anObject),但不是 add(aString)。那么, String 是一个 Object ,所以 add(aString)仍然可以编译。






另请参阅












问题



关于泛型键入规则:







    • 解释原始类型 List List< Object> 的不同之处,它与<$ c



















      $ b $ p
      $ b

      在使用超级扩展







        • 来自 Effective Java 2nd Edition :producer extends consumer super




      • (您不能!)

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

      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 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.

      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;
      

      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!
      

      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
      

      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>!

      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.


      A non-array example

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

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

      And you have these variable declarations:

      Integer anInteger
      Number aNumber
      Object anObject
      String 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.


      See also

      Related questions

      On generics typing rules:

      On using super and extends:

      这篇关于使用“超级”关键字绑定泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 01:51