A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 顾传文 中级黑马   /  2013-3-4 14:16  /  1864 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 顾传文 于 2013-3-5 17:11 编辑

int[] arr1 = new int[3];
System.out.println(arr1[1]);//输出结果为:0
Integer[] arr2 = new Integer[3];
System.out.println(arr2[1]);//数据结果为:null
List<Integer> list = new ArrayList<Integer>();
System.out.println(list.get(1));//角标越界

请问:ArrayList底层的数据结构是数组,而且初始化时构造一个初始容量为 10 的空列表。
为什么int[]数组和Integer[]数组可以取出第2个元素,而集合却出现角标越界异常呢?

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

7 个回复

倒序浏览
{:soso_e132:}俺也不知道呀! 还是先抢个沙发坐坐先 {:soso_e120:}
回复 使用道具 举报
int[] arr1 = new int[3];
                System.out.println(arr1[1]);//输出结果为:0
                Integer[] arr2 = new Integer[3];
                System.out.println(arr2[1]);//数据结果为:null
                List<Integer> list = new ArrayList<Integer>();
                System.out.println(list.get(1));//角标越界------------=这代表你创建一个ArrayList集合,他初始化为空
                                                                                //而你上面写的数组,都是已经确定大小的,并且在创建时,系统已经隐式的赋了值.空的容器里面没有对象.
                                                                                //当你想往里面加入东西时,才有东西可取.否则就是一个空瓶子
                //容器和数组是不一样的.数组的特性:创立必须确定大小,而容器虽然使用他的结构,但是并不代表他使用他的结构就变成了数组.

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
如何允许你访问,则说明集合中已经有元素了,元素为null
但事实上并没有向集合中增加元素
所以不会允许你访问的
回复 使用道具 举报
从ArrayList的源码中可以解决楼主的问题,ArrayList的get方法定义
public E get(int index) {
        RangeCheck(index);  //此处会进行检查
       //RangeCheck(index)定义
          /*private void RangeCheck(int index) {
        if (index >= size)  //当前size为0,index为1 所以抛出IndexOutOfBoundsException
            throw new IndexOutOfBoundsException(
                "Index: "+index+", Size: "+size);
    }*/

        return (E) elementData[index];
    }

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
当引用型变量没有任何实体指向的时候,还在该变量操作具体的实体时,就会发生该异常。
回复 使用道具 举报
数组是JAVA语言内置的数据类型,它是一个线性的序列,所以它可以快速的访问其他的元素。但是速度是要有代价的,当你创建了一个数组之后,它的容量就固定了,而且在其生命周期里是不能改变的。还有一点,JAVA里面的数组是会做边界检查的,所以当你越界访问时,会抛出RuntimeException,所以不用担心在C或C++因为不做边界检查而出现的问题了,当然边界检查是以牺牲效率为代价的。数组与其它容器类的区别体现在三个方面:效率、类型识别和可以持有primitives。     JAVA里面提供的其他容器还包括List,Set和Map。他们处理对象的时候就好像这些这些对象都没有自己的类型一样,容器将它所含的元素都看成是JAVA中所有类的根类Object类型的,这样我们只需创建一种容器,就能把所有的类型的对象全部放进去。但是当取出的时候,那就需要我们自己进行类型转换了,不过在JAVA Tiger版里面新引入了“泛型”的概念,结合容器类一起使用就可以解决类型转换的问题,关于“泛型”这就不详细讲解了。从上面的角度来看,这种做法很不错,但是就是苦了primitives,如果是常量的话,可以把primitive转换成wrapper类然后放进容器里面,如果是变量的话,那就只能放在你自己的类里了。与其他容器类相比,数组会在编译的时候作类型检查,从而防止你插入错误类型的对象,或者在提取对象的时候把对象的类型给搞错了,JAVA在编译和运行的时候都能阻止你将一个不恰当的消息传给对象。至于效率,数组无疑是要高于其他容器类的,因为有些容器类的实现就是基于数组的,比如ArrayList。不论从类型检查还是效率的角度来考虑,我们首选数组来作为容器都是没错的,但是数组的缺点就是功能太弱了,所以才会有容器类的出现。     要多说几句的就是,java.util包里面有一个Arrays类,它包括了一组可以用于数组的static的工具方法,其中最基本的是四个方法:用来比较两个数组是否相等的equals();用来填充数组的fill();用来对数组进行排序的sort();以及用于在一个已经排序的数组中查找元素的binarySearch()。所有这些方法都对primitives和Object进行了重载。此外还有一个asList()方法,它接受一个数组,然后把它转成一个List容器。JAVA标准类库还提供了一个System.arraycopy()的静态方法,它能以较快的速度拷贝数组,对primitive和Object都进行了重载,但是注意当对Object数组进行拷贝时,进行的是浅拷贝(shallow copy)。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马