4.5 数组类型
数组也是一种类型。它本身是引用类型。例如int是一种基本类型,int[]就是引用类型。
两种定义数组的方式:
1.type[] arrayName;
2.type arrayName[];
通常推荐第一种写法,这种方法既容易理解,也符合定义变量的语法。
如果访问数组元素时指定的索引值小于0,或者大于等于数组的长度,编译程序不会出现任何错误,但运行时会抛出异常
4.5.5foreach循环
String[] books={"三国演义","西游记","红楼梦"}; for (String book:books) { System.out.println(book); }
但是有一点,使用foreach来迭代数组元素时,foreach中的循环变量相当于一个临时变量,系统会把数组元素一次赋给这个临时变量,而这个临时变量并不是数组元素,它只保存了数组元素的值,因此,如果希望改变数组元素的值,则不能使用foreach循环。
4.6深入数组
实际数组对象被存储在堆(heap)内存中;如果引用该数组对象的数组引用变量是一个局部变量,那么它被存储在栈(stack)内存中。具体示意图看课本P92.
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块内存栈中,随着方法的执行结束,这个方法的内存栈也将自然销毁。因此所有在方法中的局部变量都要放在栈内存中的;在程序中建立一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的建立成本比较大),这个运行时数据区就是堆内存。堆内存对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(在方法参数传递时很常见),则这个方法依然不会销毁,只有当一个对象没有任何引用类型引用它时,系统的垃圾回收机器才会在合适的时候回收它。
int [] a={5,7,20}; int [] b=new int[4]; b=a;
上边程序的实际上是a=b={5,7,20};
注意此处:不是把a数组的内容给了b,而是把a的地址给了b,现在a和b都指向那个{5,7,20}的数组。第二个数组失去了引用,变成了垃圾,只有等垃圾回收机制来回收它。具体示意图看课本p93
一定要把数组看成两部分:一个部分时数组的引用,也就是代码中定义的数组引用变量;还有一部分是实际的数组对象,这部分是在堆内存里运行的,通常无法直接访问到它,只能通过数组引用变量来访问它。
4.6.4没有多维数组
type[][] arrName类似于二维数组,实质上还是一维数组,只是其数组元素也是引用,数组元素里保存的引用指向一维数组。
但是要注意的是,不可以用这个方法生成三维四维以致更高的维度。比如int [][] a;前边我们已经说过了,int[]是一种类型,那么这个数组表明数组a中存放的是int[]类型的数据。如果要定义多维数组,可以定义一个Object[]类型的数组,这个数组的元素是Object类型的数组,合格数组元素可以再次指向一个Object[]类型的数组,这样就可以从一维数组扩展到二维数组、三维数组……
java提供的Array类里包含的一些static修饰的方法可以直接操作数组,这个Arrays类里包含了一些static修饰的方法:
int binarySearch(type[] a,type key):使用二分法查询key元素值在a数组中出现的索引;如果a数组不存在,则返回负数。要数组元素已经按照升序排列。
还有一些并行工具方法,充分利用多cpu并行能力来提高设值和排序的能力:
void parallelSort(xxx[] array):排序