在Java中,为什么数组不能是类型变量的绑定,但可以是通配符的绑定?

Joh*_*oth 10 java arrays wildcard bounds type-parameter

在Java中,为什么数组不能是类型变量的绑定,但可以是通配符的绑定?

你可以有:

List< ? extends Integer[] > l;
Run Code Online (Sandbox Code Playgroud)

但你不能拥有:

class MyClass< T extends Integer[] > { } // ERROR!
Run Code Online (Sandbox Code Playgroud)

为什么?

Fav*_*ius 7

考虑这个Java代码:

package test;

public class Genric<E>
{
    public Genric(E c){
        System.out.println(c.getClass().getName());
    }   
    public static void main(String[] args) {
        new Genric<Integer[]>(new Integer[]{1,2});
    }
}
Run Code Online (Sandbox Code Playgroud)

对于你的第一个案例:

List< ? extends Integer[] > l;
Run Code Online (Sandbox Code Playgroud)

当您执行类似这样List< ? extends Integer[] > l;的操作时,Java编译器会将其视为a List< ? extends Object> l;并相应地进行转换.所以这就是为什么你没有得到任何错误.

生成的字节码如下:

   .
   .
   .
   20:  aastore
   21:  invokespecial   #52; //Method "<init>":(Ljava/lang/Object;)V
   24:  return
   .
   .
Run Code Online (Sandbox Code Playgroud)

查看第21行.虽然,我已经通过了一系列的java.lang.Integer; 在内部它被翻译成java.lang.Object.

对于你的第二个案例:

class MyClass< T extends Integer[] > { } // ERROR!
Run Code Online (Sandbox Code Playgroud)

根据java语言规范:

TypeParameter:
TypeVariable TypeBoundopt

TypeBound:
extends ClassOrInterfaceType AdditionalBoundListopt
.
.
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,绑定仅由类或接口组成(甚至不是原始类型).所以,当你做这样的事情class MyClass< T extends Integer[] > { }Integer[]没有资格作为一个类或接口.

根据我对Java Spec的理解,这样做是为了解决所有场景

  1. class MyClass< T extends Integer[] >
  2. class MyClass< T extends Integer[][] >
  3. ..
  4. class MyClass< T extends Integer[][]...[] >

因为所有这些都可以表示为java.lang.Object和作为参数传递时,如示例所示

public Genric(E c){
            System.out.println(c.getClass().getName());
        }
Run Code Online (Sandbox Code Playgroud)

因为'c'记得它的真实类型.

希望这会有所帮助.