类型数组 与c 泛型数组的区别?什么时候用数组 什么时候用泛型?

Java中有关泛型集合和数组的疑惑? - 知乎27被浏览826分享邀请回答List&Integer& li = new ArrayList&Integer&();
List&Number& ln = // illegal
ln.add(new Float(3.1415));
如果允许泛型协变,调用li.get(0),得到的按理说应该是个Integer,但实际上确实一个Double。用array编译不会报错,但runtime时会在赋值这一步抛出异常(ArrayStoreException),因为array在创建时就已经绑定了类型。可以使用泛型通配符(wildcard)来实现多态,就更没必要让泛型协变了,比如上面说到的compare(Object[] arr1, Object[] arr2)用泛型通配符可以写成:compare(List&? extends Number& list1, List&? extends Number& list2)
其实我都是搬运的,加强英语多用google吧:0添加评论分享收藏感谢收起Java加强(3)
import java.util.ArrayL
TestArrayAndaGeneric
public static void main(String[] args)
ArrayList&String& al = new ArrayList();//不报错,但al不能添加String类型以外的对象作为元素
//al.add(15);//报错
al.add(&hafahha&);
//下面两句不报错,泛型在编译时期严格进行语法检查,一行一行编译代码,所以不报错
//源程序被编译后的字节码不带泛型,所以添加元素也没问题
ArrayList al2 = new ArrayList&String&();
ArrayList&Integer& al3 = al2;
al3.add(8);
//al3.add(&haha&);//报错,编译时al3带着泛型,al3只能添加Integer类型对象
System.out.println(al3.size());
System.out.println(al3.get(0));
//数组与泛型,数组不同于泛型,数组编译时不报错,但运行时报错,因为数组类型一直到运行时期仍然还在。
Object[] obj = new String[4];
//obj[2] = 7;//报错
//System.out.println(obj[2]);
ArrayList[] alList1 = new ArrayList[5];
ArrayList&String&[] alList2 = new ArrayList[3];
alList2[0] = new ArrayList();
alList2[1] = new ArrayList&String&();
//alList2[2] = new ArrayList&Object&();//错误: 不兼容的类型
alList2[0].add(&hehe&);
//alList2[0].add(4);// 错误: 对于add(int), 找不到合适的方法
//ArrayList&String&[] alList3 = new ArrayList&String&[8];//错误:创建泛型数组
//初步理解:java中允许定义泛型数组,但不允许创建泛型数组;定义了泛型数组,则编译时期泛型会一直跟随数组。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:10433次
排名:千里之外
原创:22篇
(5)(5)(12)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'java为什么不支持泛型数组? - 知乎135被浏览20073分享邀请回答cr.openjdk.java.net/~briangoetz/valhalla/specialization.html&- 这篇文档主要讨论的是原本Java泛型的设计取舍以及当前在实验中的改进思路。注意这篇文档里的“未来版本Java”的语法都是为了实现原型而随便选用的语法,不是经过彻底设计调整后的语法;请不要对原型的语法吐槽,语法是最表面最容易变的部分。Java的reified generics目标是在Java 10推出。目前有原型可以玩:484 条评论分享收藏感谢收起List&String& l = new ArrayList&String&();
l.add("hello");
String str=l.get(0);
运行时,类型参数&String&都被擦掉,只有在最后读取内部元素的时候,才插入一个类型转换。看起来就像下面这样,List l = new ArrayList&String&();
List.add("hello");
String str=(String)List.get(0);
所以,如果像下面这样初始化泛型数组的话,List&String&[] l = new ArrayList&String&[10];
运行时编译器只能看到ArrayList,而看不到泛型的String类型参数。数组由于无法确定所持有元素的类型,所以不允许初始化。Java Language Specification明确规定:数组内的元素必须是“物化”的。It is a compile-time error if the component type of the array being initialized is not reifiable.对“物化”的第一条定义就是不能是泛型:A type is reifiable if and only if one of the following holds:It refers to a non-generic class or interface type declaration.... ...因为Array的具体实现是在虚拟机层面,嵌地非常深,也查不到源码。只好用javap反编译看看具体初始化数组的字节码。我们反编译下面一段代码:初始化一个String数组和一个int数组。String[] s=new String[]{"hello"};
int[] i=new int[]{1,2,3};
反编译的片段如下:
0: iconst_1
1: anewarray
// class java/lang/String
5: iconst_0
// String hello
8: aastore
9: astore_1
10: iconst_3
11: newarray
14: iconst_0
15: iconst_1
其中:"1: anewarray
#2":创建String数组"11: newarray
int":创建int数组anewarray和newarray都是虚拟机内部用来创建数组的命令。最多只能有2的8次方256个操作码,光创建数组就占了不止一个,可见数组的地位有多特殊。其中newarray用atype来标记数组类型。anewarray用index来标记。从描述里可以看到,数组除了元素类型,还有一个必须确定的是长度,因为数组是一段连续内存。查一下
对anewarray命令的描述,anewarray &type&&type& indicates what types of object references are to be stored in the array. It is either the name of a class or interface, e.g. java/lang/String, or, to create the first dimension of a multidimensional array, &type& can be an array type descriptor, e.g.[Ljava/lang/S比如anewarray字节码命令的格式就是anewarray后面跟一个具体的元素类型。所以不能确定&type&的确切类型,就无法创建数组。最初在还没有泛型的时候,数组就一直是以“The Special One”的形象出现。那个时候所有容器都还只是持有Object。在其他容器都不太关心类型安全的年代,数组就特立独行地坚持类型检查,它的使命就是提供一个“类型安全”和效率更高的容器。所以类型检查和长度限制都被写到了字节码的规范里。至于到了支持泛型的年代,泛型“泛化”的本质就和数组“精确高效”的主旨根本上是相违背的。而且要改的话就要在字节码里动刀了。还是历史包袱的问题。6715 条评论分享收藏感谢收起查看更多回答

我要回帖

更多关于 swift 泛型数组 的文章

 

随机推荐