String[] s=new String[]{"hello"}; int[] i=new int[]{1,2,3}; //Array的具体实现是在虚拟机层面,嵌地非常深,也查不到源码 //只能用javap反编译看看具体初始化数组的字节码
下面是具体的反编译的字节码: 看注释说明,创建int数组和String数组的指令都不一样,换句话说,数组是Java中的特例,它嵌在虚拟机层面,从底层就决定了不支持泛型
Code:
0: iconst_1
1: anewarray #2 // class java/lang/String
4: dup
5: iconst_0
6: ldc #3 // String hello
8: aastore
9: astore_1
10: iconst_3
11: newarray int
13: dup
14: iconst_0
15: iconst_1
... ...
看来协变的概念就应该很清楚的知道,泛型是不支持协变的。List<integer> 并不是 List<Number>的儿子。编译期就会报错,如下截图
于是,java设计者引入了通配符的概念,用于在泛型中提供协变这一功能。比如 我们希望有一个方法,它即可以接受宠物狗列表,也可以接受田园犬(是宠物狗的子类)列表,
于是我们引入协变。
package com.generic;
import java.util.ArrayList;
import java.util.List;
public class PetShow {
public void run(List<? extends ChongWuGou> dogs){
System.out.println("running");
}
public static void main(String [] args){
List<ChongWuGou> cDogs = new ArrayList<ChongWuGou>();
List<TianYuanQuan> tDogs = new ArrayList<TianYuanQuan>();
new PetShow().run(tDogs);//该方法可以正确运行
}
}
//宠物狗
class ChongWuGou{
}
class TianYuanQuan extends ChongWuGou{
}
在Java中不允许将父类变量赋值给子类变量。泛型自然也不支持逆变。但是在泛型中可以通过通配符进行模拟
public class Test
{
public static void main(String[] args)
{
List<? super Integer> list = new ArrayList<Number>();
}
}
? super Integer的含义是:支持Integer的父类,也包括Integer类,作为泛型的参数。