1.1数组初始化
数组是大多数编程语言都提供一种复合结构,如果程序需要多个类型相同的变量时,就可以考虑定义一个数组。java语言的数组变量引用是引用类型的变量,因此具有java独有的特性。
1.1. java数组是静态的
java语言是典型的静态语言,因此java的数组是静态的,即当数组被初始化之后,该数组的长度是不可变的。java程序中的数组必须初始化才可使用。所谓初始化,就是为数据对象元素分配内存空间,并为每个数组元素指定初始值。
数组的初始化有以下两种方式。
静态初始化:初始化时由程序员显示指定每个数组元素的初始值,由系统决定数组长度。
动态数据初始化:初始化时程序员只指定数据长度,由系统为数组元素分配初始值。
不管采用哪个方式初始化java数组,一旦初始化完成,该数组的长度就不可改变,java语言允许通过数组lenght属性来访问数组的长度。示例如下:
public class ArrayTest
{
public static void main(String[] args)
{
//采用静态初始化方式初始化第一个数组
String[] books = new String[]
{
"疯狂Java讲义",
"轻量级Java EE企业应用实战",
"疯狂Ajax讲义",
"疯狂XML讲义"
};
//采用静态初始化的简化形式初始化第二个数组
String[] names =
{
"孙悟空",
"猪八戒",
"白骨精"
};
//采用动态初始化的语法初始化第三个数组
String[] strArr = new String[5];
//访问3个数组的长度
System.out.println("第一个数组的长度:" + books.length);
System.out.println("第二个数组的长度:" + names.length);
System.out.println("第三个数组的长度:" + strArr.length);
}
}
上面程序中的粗体字代表声明并初始化了3个数组,这3个数组的长度将会始终不变,程序输出3个数组的长度依次为4、3、5。
前面已经指出,java语言的数组变量是引用类型的变量,books、names、seansonsp这3个变量以及各自引用的数组在内存中的分配如图1.1所示。
从图1.1中可以看出,对于静态初始化方式而言,程序员无需指定数组长度,指定数组的数组元素,由系统来决定该数组的长度即可。例如books数组,为它指定了4个数组元素,那它的长度就是4,对于name数组,为它指定3个元素,那它的长度就是3。
执行动态初始化时,程序员只需指定数组的长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。指定初始化值时,系统将按如下规则分配初始化值。
数组元素的类型是基本类型中的整数类型(byte、short、int和long),则数组元素的值是0。
数组元素的类型是基本类型中的浮点类型(float、double),则数组元素的值是0.0。
数组元素的类型是基本类型中的字符类型(char),则数组元素的值是'\u0000'。
数组元素的类型是基本类型中的布尔类型(boolean),则数组元素的值是false。
数组元素的类型是引用类型(类、接口和数组),则数组元素的值是null。
注意:不要同时使用静态初始化和动态初始化。也就是说,不要在进行数组初始化时既指定数组的长度,也为每个数组元素分配初始值。
java的数组是静态的,一旦为数组初始化完成,数组元素的内存空间分配即结束,程序只能改变数组元素的值,而无法改变数组的长度。
需要指出的是,java的数组变量是一种引用类型的变量,数组变量并不是数组本身,它只是指向堆内存中的数组对象。因此,可以改变一个数组变量所引用的数组,这样可以造成数组长度可变的假象。假设,在上面程序后面增加如下几行。
程序清单:codes
{
public static void main(String[] args)
{
//采用静态初始化方式初始化第一个数组
String[] books = new String[]
{
"疯狂Java讲义",
"轻量级Java EE企业应用实战",
"疯狂Ajax讲义",
"疯狂XML讲义"
};
//采用静态初始化的简化形式初始化第二个数组
String[] names =
{
"孙悟空",
"猪八戒",
"白骨精"
};
//采用动态初始化的语法初始化第三个数组
String[] strArr = new String[5];
//访问3个数组的长度
System.out.println("第一个数组的长度:" + books.length);
System.out.println("第二个数组的长度:" + names.length);
System.out.println("第三个数组的长度:" + strArr.length);
//让books数组变量、strArr数组变量指向names所引用的数组
books = names;
strArr = names;
System.out.println("--------------");
System.out.println("books数组的长度:" + books.length);
System.out.println("strArr数组的长度:" + strArr.length);
//改变books数组变量所引用的数组的第二个元素值。
books[1] = "唐僧";
System.out.println("names数组的第二个元素是:" + books[1]);
}
}
上面程序中粗体字代码将记books数组变量、strArr数组变量都指向names数组变量所引用的数组,这样做的结果就是books、strArr、names这3个变量引用同一个数组对象,此时,3个引用变量和数组对象在内存中的分配如图1.2所示。
从图1.2可以看出,此时strArr、names和book数组变量实际上引用同一个数组对象,因此,当访问books数组、strArr数组的长度时,将看到输入3。这很容易造成一个假想:books数组的长度从4变量了3。实际上,数组对象本身的长度并没有发生改变,变的是books数组变量。books数组变量原本指向堆内存下面的数组,当执行了books=names;语句之后,books数组将改为指向堆内存中间的数组,而原来books变量所引用的数组的长度依然是4。
当然,从图1.2中还可以看出,原来books变量所引用的数组长度依然是4,但不再有任何引用变量引用该数组,因此它将会变成垃圾,等着垃圾回收机制来回收,此时,程序使用books、names和strArr这3个变量时,将会访问同一个数组对象,因此把books数组的第2个元素赋值为"唐僧"时,names数组的第2个元素的值也会随之改变.
与java这种静态语言不同的是,javascript这种动态语言的数组长度是可以动态改变的,示例如下:
<script type="text/javascript">
var arr = [];
document.writeln("arr的长度是:" + arr.length + "<br/>");
//为arr数组的两个数组元素赋值
arr[2] = 6;
arr[4] = "孙悟空";
//再次访问arr数组的长度
document.writeln("arr的长度是:" + arr.length + "<br/>");
</script>
上面是一个简单的javascrip程序,它先定义了一个名为arr的空数组,因为它不包含任何数组元素,所以它的长度是0,接着,为arr数组的第3个,第5个元素赋值,该数组的长度也是自动变为5。这就是javascript里动态数组和java里静态数组的区别。