一、数组初始化
Java 中的数组变量是引用类型的变量。
Java 是静态语言,因此 Java 数组是静态的,即当数组初始化之后,该数组所占的内存空间、数组长度都是不变的。
1、Java 中数组初始化的两种方式:
- 静态初始化:初始化时由程序显示指定每个数组元素的初始值;
- 动态初始化:初始化时只指定数组长度,由系统分配初始值。
public static void main(String[] args) {
// 静态初始化第一个数组
String[] books = new String[] {
"hhh",
"2333"
};
// 静态初始化第二个数组
String[] names = {
"aaa",
"bbb",
"ccc"
};
// 动态初始化第三个数组
String[] aStr = new String[5];
System.out.println("books 长度: " + books.length);
System.out.println("names 长度: " + names.length);
System.out.println("aStr 长度: " + aStr.length);
}
输出:
静态初始化方式由系统决定该数组长度;
而动态初始化方式只需指定数组的长度,由系统按如下规则分配初始值:
- 整数类型(byte, short, int, long):初始值为 0;
- 浮点类型(float, double):初始值为 0.0;
- 字符类型(char):初始值为 ‘\u0000’,即 空格的 Unicode 编码;
- 布尔类型(boolean):初始值为 false;
- 引用类型(类,接口和数组):初始值为 null 。
2、Java 数组长度不可变(即 Java 数组是静态的):
Java 中一旦数组初始化完成,数组的内存空间分配即结束,程序只能改变数组元素的值,而无法改变数组的长度。但由于 Java 数组是引用类型的变量,因此可以改变一个数组变量所引用的数组,可以造成数组长度可变的假象。
public static void main(String[] args) {
String[] books = new String[] {
"hhh",
"2333"
};
String[] names = {
"aaa",
"bbb",
"ccc"
};
books = names;
// 修改 books 数组变量所引用的数组的第二个元素
books[1] = "wlm";
System.out.println("names 数组第二个元素: " + names[1]);
}
输出为:
操作说明:
3、使用 Java 数组之前必须进行初始化
代码说明如下:
public static void main(String[] args) {
// 定义并初始化 nums 数组
int[] nums = new int[] {1, 2, 3, 4};
// 定义 prices 数组变量
int[] prices;
// prices 数组变量指向 nums 所引用的数组
prices = nums;
System.out.println("输出 prices 数组: ");
for (int i = 0; i < prices.length; i ++) {
System.out.print(prices[i] + " ");
}
System.out.println();
// 修改 nums 数组第三个元素
prices[2] = 111;
System.out.println("nums 第三个元素: " + nums[2]);
}
输出为:
这里的 Java 数组的初始化指的是对 Java 对象进行初始化,而不是对数组变量执行初始化。即在 堆内存 中创建数组对象,也就是为该数组对象分配一块连续的内存空间,这块连续空间的长度就是数组的长度。
即 Java 程序中的引用变量并不需要进行初始化操作,需要进行初始化的是引用变量所引用的对象。
注:Java 局部变量必须制定初始值,如引用之前未指定,则会报编译错误。
4、基本类型数组初始化
程序先为数组分配内存空间,再将数组元素的值存入对应内存里。数组变量存于栈内存中,数组对象存于堆内存中。且一旦数组对象创建成功,数组长度不可改变。
public static void main(String[] args) {
// 定义 int[] 类型数组变量
int[] arr;
// 静态初始化数组, 数组长度为 4
arr = new int[]{1, 2, 3, 4};
}
执行代码 int[] arr 时,仅定义一个数组变量,内存分配如下:
仅在main栈区定义了一个 arr 变量。
执行 arr = new int[]{1, 2, 3, 4} 静态初始化之后,系统根据数组元素来决定数组的长度。此处数组长度为4,一旦数组对象创建成功,该数组长度不可变,程序只能改变数组元素的值。此时内存分配如下:
说明:
- 所有局部变量都是放在栈内存中的,不管是基本类型的变量,还是引用类型的变量;
- 但引用类型的变量所引用的对象则总是存储在堆内存中。
5、引用类型数组初始化
引用类型的数组元素是引用类型的,因此数组元素里存储的是引用,指向另一块内存,该内存存储了该引用变量所引用的对象(包括数组和java对象)。
代码说明如下:
Person 类:
package com.tide.test;
/**
* Created by wengliemiao on 16/4/4.
*/
public class Person {
private int age; // 年龄
private double weight; // 身高
// 定义一个 info 方法
public void info() {
System.out.println("我的年龄是: " + age + ", 我的身高是: " + weight);
}
}
Run 类:
package com.tide.test;
/**
* Created by wengliemiao on 16/4/4.
*/
public class Run {
public static void main(String[] args) {
// 定义一个 students 数组变量, 类型是 Person[]
Person[] students ;
// 动态初始化
students = new Person[2];
System.out.println("students 引用数组长度是: " + students.length);
// 创建一个 Person 实例, 并将这个 Person 实例赋给 wlm 变量
Person wlm = new Person();
wlm.setAge(21);
wlm.setWeight(70);
// 创建一个 Person 实例, 并将这个 Person 实例赋给 sunlei 变量
Person sunlei = new Person();
sunlei.setAge(21);
sunlei.setWeight(60);
// 将 wlm 变量赋给第一个数组元素
students[0] = wlm;
// 将 sunlei 变量赋给第二个数组元素
students[1] = sunlei;
// 输出
wlm.info();
students[0].info();
}
}
输出为:
上面的代码代表了引用类型数组初始化的典型过程。
内存分配过程如下:
执行 Person[] students 时定义一个引用类型的数组变量:
执行动态初始化,由系统为数组元素分配默认的初始值 null:
定义 wlm 和 sunlei 两个引用变量,并指向堆内存中的 Person 对象:
students 数组的元素也是引用类型的变量,也可以指向堆内存中的对象:
此处students[0] 和 wlm 指向同一个 Person 对象,students[1] 和 sunlei 指向同一个 Person 对象,因此 info 输出结果一致。
二、使用数组
- 数组元素就是变量;
- Java 中没有多维数组。
多维数组就是数组元素为数组的一维数组;
二维数组是数组元素为一维数组的数组;
三维数组是数组元素为二维数组的数组;
……
Java 允许将多维数组当成一维数组处理。
package com.tide.test;
/**
* Created by wengliemiao on 16/4/4.
*/
public class Run {
public static void main(String[] args) {
Object[] objArr = new Object[3];
objArr[1] = new Object[2];
Object[] objArr2 = (Object[]) objArr[1];
objArr2[1] = new Object[3];
Object[] objArr3 = (Object[]) objArr2[1];
objArr3[1] = new int[5];
int[] iArr = (int[]) objArr3[1];
for (int i = 0; i < iArr.length; i ++) {
iArr[i] = i * 3 + 1;
}
System.out.println( ((int[]) ((Object[]) ((Object[]) objArr[1]) [1]) [1]) [2]);
}
}
输出为:
内存分配为: