如果是编译时的,那岂不是和C++那样会产生非常严重的代码膨胀?
但是网上说,范型代码只有一份代码拷贝,所以看起来是运行时的范型。但是,
如果是运行时的范型的话,不同代码膨胀的办法,只维护一份代码,那么如何才能确定真正的类型呢?
这有点悖论了.牛人指点一下迷津哈!
但是网上说,范型代码只有一份代码拷贝,所以看起来是运行时的范型。但是,
如果是运行时的范型的话,不同代码膨胀的办法,只维护一份代码,那么如何才能确定真正的类型呢?
这有点悖论了.牛人指点一下迷津哈!
问题是,我编译产生的中间结果里面,保存了"第一个List是String,第2个List是Interger"这样的信息么?不然的话,jvm如何知道转为哪个类型?
这样的话,我的类型去哪里了,jvm在运行时到哪里去找回这个类型呢?
List<String>,List<Integer>编译之后可以理解成统统变成List<Object>了“jvm如何知道转为哪个类型”这个问题就更容易实现了,在编译的时候编译器自动加上强制转换就OK了
看下面的代码 ArrayList<String> list=new ArrayList<String>();
ArrayList t=new ArrayList();
t.add(new Object());
list.addAll(t);这时list中的第一个元素其实是Object,而不是String,运行时不会报错;关于为什么没有产生多份代码的问题,是这样的:
java中的泛型只针对对象,不能用基本数据类型,我们不能这样ArrayList<int> t=new ArrayList<int>();
所以代码在本质上是一样的,只是在使用的地方,编译器自动加上了类型强转,比如:
//ArrayList<String> list=new ArrayList<String>();
String s=list.get(0);
编译器把它自动变成String s=(String)list.get(0);
import java.util.*;
public class Test {
public static void main(String... args) {
List<String> list = new ArrayList<String>();
String value = list.get(0);
}
}
编译后通过javap -c Test命令得出main方法伪指令如下:public static void main(java.lang.String[]);
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: iconst_0
10: invokeinterface #4, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
15: checkcast #5; //class java/lang/String
18: astore_2
看那个checkcast
import java.util.ArrayList;
import java.util.List;public class Test
{
public static void main(String[] paramArrayOfString)
{
ArrayList localArrayList = new ArrayList();
String str = (String)localArrayList.get(0);
}
}说明编译之后没有泛型的概念了