数组的存储

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

在上一篇中,我们已经了解了数组,它是一种引用类型,本篇将详细介绍数组的内存分配等知识点。数组用来存储同一种数据类型的数据,一旦初始化完成,即所占的空间就已固定下来,即使某个元素被清空,但其所在空间仍然保留,因此数组长度将不能被改变。当仅定义一个数组变量(int[]numbers)时,该变量还未指向任何有效的内存,因此不能指定数组的长度,只有对数组进行初始化(为数组元素分配内存空间)后才可以使用。数组初始化分为静态初始化(在定义时就指定数组元素的值,此时不能指定数组长度)和动态初始化(只指定数组长度,由系统分配初始值)。//静态初始化int[]numbers=newint[]{3,5,12,8,7};String[]names={Miracle,MiracleHe};//使用静态初始化的简化形式//动态初始化int[]numbers=newint[5];String[]names=newString[2];建议不要混用静态初始化和动态初始化,即不要既指定数组的长度的同时又指定每个元素的值。当初始化完毕后,就可以按索引位置(0~array.length-1)来访问数组元素了。当使用动态初始化时,如在对应的索引位未指定值的话,系统将指定相应数据类型对应的默认值(整数为0,浮点数为0.0,字符为'\u0000',布尔类型为false,引用类型为null)。publicclassTestArray{publicstaticvoidmain(String[]args){String[]names=newString[3];names[0]=Miracle;names[1]=MiracleHe;//以下代码将输出MiracleMiracleHenull/*for(inti=0;inames.length;i++){System.out.print(names[i]+);}*///还可以使用foreach来遍历for(Stringname:names){System.out.print(name+);}}}请注意:java中是没有foreach这个关键字的,其语法是for(typeitem:items)来表示,但foreach只能用于遍历元素的值而不能改变,必须使用for才能实现。publicclassTestForEach{publicstaticvoidmain(String[]args){int[]numbers={3,5,12,8,7};for(intnumber:numbers){intnum=number*10;System.out.print(num+,);}System.out.println();//numbers仍然未发生变化(如果换成for将改变)for(inti=0;inumbers.length;i++){System.out.print(numbers[i]+,);}}}以上简单的介绍了数组的初始化和应用,接下来讲详细介绍数组(数组引用和数组元素)在内存中的存放形式。首先给出结论:数组引用变量是存放在栈内存(stack)中,数组元素是存放在堆内存(heap)中,通过栈内存中的指针指向对应元素的在堆内存中的位置来实现访问,以下图来说明数组此时的存放形式。那什么是栈内存和堆内存呢?我举例作一一解释。当执行方法时,该方法都会建立自身的内存栈,以用来将该方法内部定义的变量逐个加入到内存栈中,当执行结束时方法的内存栈也随之销毁,我们说所有变量存放在栈内存中,即随着寄存主体的消亡而消亡;反之,当我们创建一个对象时,这个对象被保存到运行时数据区中,以便反复利用(因为创建成本很高),此时不会随着执行方法的结束而消亡,同时该对象还可被其他对象所引用,只有当这个对象没有被任何引用变量引用时,才会在垃圾回收在合适的时间点回收,我们说此时变量所指向的运行时数据区存在堆内存中。只有类型兼容(即属于同一数据类型体系且遵守优先级由低到高原则),才能将数组引用传递给另一数组引用,但仍然不能改变数组长度(仅仅只是调整数组引用指针的指向)。publicclassTestArrayLength{publicstaticvoidmain(String[]args){int[]numbers={3,5,12};int[]digits=newint[4];System.out.println(digits数组长度:+digits.length);//4for(intnumber:numbers){System.out.print(number+,);//3,5,12,}System.out.println();for(intdigit:digits){System.out.print(digit+,);//0,0,0,0,}System.out.println();digits=numbers;System.out.println(digits数组长度:+digits.length);//3}}虽然看似digits的数组长度看似由4变成3,其实只是numbers和digits指向同一个数组而已,而digits本身失去引用而变成垃圾,等待垃圾回收来回收(但其长度仍然为4),但其内部运行机制如下图所示。因此当我们看一个数组时(或者其他引用变量),通常看成两部分:数组引用变量和数组元素本身,而数据元素是存放在堆内存中,只能通过数组引用变量来访问。从上述的示例中看出数组中存放的是基本类型,其实数组中还可以存放引用类型的。而存放基本类型的内存分布已经解释了,而存放引用类型的内存分布则相对复杂了。来看一段非常简单的程序。publicclassTestPrimitiveArray{publicstaticvoidmain(String[]args){//1.定义数组int[]numbers;//2.分配内存空间numbers=newint[4];//3.为数组元素指定值for(inti=0;inumbers.length;i++){numbers[i]=i*10;}}}按以上步骤的内存分布示意图:从图中可看出数组元素直接存放在堆内存中,当操作数组元素时,实际上是操作基本类型的变量。接下来再看一段程序:classPerson{publicintage;publicStringname;publicvoiddisplay(){System.out.println(name+的年龄是:+age);}}publicclassTestReferenceArray{publicstaticvoidmain(String[]args){//1.定义数组Person[]persons;//2.分配内存空间persons=newPerson[2];//3.为数组元素指定值Personp1=newPerson();p1.age=28;p1.name=Miracle;Personp2=newPerson();p2.age=30;p2.name=MiracleHe;persons[0]=p1;persons[1]=p2;//输出元素的值for(Personp:persons){p.display();}}}对于数组元素为引用类型在内存中的存储与基本类型不一样,此时数组元素仍然存放引用,指向另一块内存,在其中存放有效的数据。谈到这里,不知是否有朋友要问:Java的多维数组是什么样的?我的回答是:可以有。为什么呢?从底层来看,数组元素可以存放引用类型,包含数组。也就是说在数组元素的内部还可以包含数组(如int[][]numbers=newint[length][]),也即二维数组可当作一维数组(数组长度为length)来处理,也可以同时指定多个维度的长度(如int[][]matrix=newint[length][width]),不过必须至少指定最左端的数组长度length。由此我们得出结论:任何多维数组(维度为n,n1)都当作一维数组,其数组元素为n-1维数组。publicclassTestMultiArray{publicstaticvoidmain(String[]args){//1.定义二维数组int[][]numbers;//2.分配内存空间numbers=newint[3][];//可以把numbers看作一维数组来处理for(inti=0;inumbers.length;i++){System.out.print(numbers[i]+,);//null,null,null}System.out.println();//3.为数组元素指定值numbers[0]=newint[2];numbers[0][1]=1;for(inti=0;inumbers[0].length;i++){System.out.print(numbers[0][i]+,);//0,1}}}最后,简单介绍一下Arrays(位于java.util下)的静态方法:binarySearch、copyOf、copyOfRange、equals、fill、sort、toString等方法(具体用法参见JDK)。importjava.util.Arrays;publicclassTestArrays{publicstaticvoidmain(String[]args){int[]a={3,4,5,6};int[]b={3,4,5,6};System.out.println(a和b是否相等:+Arrays.equals(a,b));//trueSystem.out.println(5在a中的位置:+Arrays.binarySearch(a,5));//2int[]c=Arrays.copyOf(a,6);System.out.println(a和c是否相等:+Arrays.equals(a,c));//falseSystem.out.println(c的元素:+Arrays.toString(c));//3,4,5,6,0,0Arrays.fill(c,2,4,1);//将c中第3个到第5个元素(不包含)赋值为1System.out.println(c的元素:+Arrays.toString(c));//3,4,1,1,0,0Arrays.sort(c);System.out.println(c的元素:+Arrays.toString(c));//0,0,1,1,3,4}}接下来,给出两个数组实际应用场景的示例。数字转化为人民币大写(简易版)五子棋游戏实现(简易版)数字转化为人民币大写程序中,利用了一维数组表示大写及单位;五子棋游戏中,利用了二维数组表示棋盘。从程序中可看到throwsException表示不处理任何异常,将在后续的篇章中继续讲解。

1 / 20
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功