在Java中,为什么数组不能是类型变量的界限,但可以是通配符的界限?
你可以有:
List< ? extends Integer[] > l;
但你不能拥有:
class MyClass< T extends Integer[] > { } // ERROR!
为什么?
在Java中,为什么数组不能是类型变量的界限,但可以是通配符的界限?
你可以有:
List< ? extends Integer[] > l;
但你不能拥有:
class MyClass< T extends Integer[] > { } // ERROR!
为什么?
考虑以下 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});
}
}
对于您的第一个案例:
List< ? extends Integer[] > l;
当您执行此类操作时List< ? extends Integer[] > l;
,Java 编译器会将其视为 a List< ? extends Object> l;
并相应地对其进行翻译。所以这就是为什么你没有得到任何错误。
生成的字节码如下:
.
.
.
20: aastore
21: invokespecial #52; //Method "<init>":(Ljava/lang/Object;)V
24: return
.
.
签出第21行。虽然,我已经传递了一个数组java.lang.Integer
;在内部它被翻译成java.lang.Object
.
对于您的第二种情况:
class MyClass< T extends Integer[] > { } // ERROR!
根据java语言规范:
TypeParameter:
TypeVariable TypeBoundopt
TypeBound:
extends ClassOrInterfaceType AdditionalBoundListopt
.
.
如您所见,绑定仅由类或接口(甚至不是原始类型)组成。因此,当您执行此类操作时,class MyClass< T extends Integer[] > { }
就Integer[]
没有资格作为类或接口。
根据我对 Java Spec 的理解,这样做是为了解决所有场景,例如
class MyClass< T extends Integer[] >
class MyClass< T extends Integer[][] >
class MyClass< T extends Integer[][]...[] >
因为它们都可以表示为java.lang.Object
并且当作为参数传递时,如示例
public Genric(E c){
System.out.println(c.getClass().getName());
}
因为'c'记住了它的真实类型。
希望这会有所帮助。
我正在尝试考虑应该禁止这样做的具体原因,但我唯一能想到的是这是一个完全不必要的结构,因为:
class Foo<T extends Integer[]> {
T bar();
}
相当于
class Foo<T extends Integer> {
T[] bar();
}
显然,通配符情况不能说相同,因此它是允许的。
您可以执行以下操作:
public class MyClass<K> {
K array;
public MyClass(K k) {
array = k;
}
或者你可以做这样的事情:
class MyClass< T extends Integer > {
...make your variable MyClass[]...
}
希望这会有所帮助,我离你所要求的并不太远。