Java数组的初始化
使用Java数组之前,我们不可避免的一步是对数组进行初始化。所谓初始化,就是为数组对象分配内存空间并为每一个数组元素赋初值。由于Java语言是典型的静态语言,所以数组一旦初始化,该数组的长度将不再改变。
数组初始化的两种方式
- 静态初始化:直接指定数组元素,而无需指定数组长度,数组的长度由系统计算指定。
- 动态初始化:只需指定数组元素的长度,由系统为数组元素分配初始值。
- 不能同时使用静态初始化和动态初始化,也就是说,不能再数组初始化时,既为每个数组元素赋初值,又同时指定数组长度。
数组元素类型 | 初始值 |
---|---|
基本类型的中的整数类型,如byte、short、int、long | 0 |
基本类型的中的浮点类型,如float、double | 0.0 |
基本类型的中的字符类型,如char | \u0000 |
基本类型的中的布尔类型,如boolean | false |
基本类型的中的引用类型,如String、类 | null |
public class ArrayTest1{
public static void main(String[] args){
// 采用数组的静态初始化方法进行初始化
int[] arrayA = new int[]{1,2,3,4};
// 采用数组的静态初始化的简单方式进行初始化
int[] arrayB = {1,2,3,4};
// 采用数组的动态初始化方法进行初始化
int[] arrayC = new int[4];
for(int i = 0; i < arrayC.length; i ++){
arrayC[i] = i;
}
}
}
内存示意图如下:
数组变量与数组对象的的区别与联系
// 问题:数组一定要进行初始化吗?
public class ArrayTest2{
public static void main(String[] args){
// 采用数组的静态初始化方法进行初始化
int[] arrayD = new int[]{1,2,3,4};
int[] arrayE;
arrayE = arrayD;
for(int i = 0; i < arrayE.length; i ++){
// 会不会报错 NullPointException (空指针异常)?
System.out.println(arrayE[i]);
}
}
}
要回答上面这个问题,首先需要搞清数组变量与数组对象之间的关系,数组变量与数组对象,是一个特别容易搞混的一个知识点。实际上,当我们类比一下C语言,就会发现,想要理解数组变量和数组对象两者之间的区别和联系实际上并不难。
- 数组变量:实际上就是一个引用变量,类似于C语言中的指针,通常存放在栈内存中(也可存放在堆内存中,例如多维数组的情况),对数组变量来说,它并不需要进行初始化操作,而只要让它指向一个有效的数组对象,程序就可以正常的使用该变量。
- 数组对象:实际上就是保存在堆内存中连续的内存空间,它是实际存放数组元素的地方。通常所说的对数组进行初始化,就是对数组对象进行的初始化——也就是为其开辟一块连续的存储空间。下图即是arrayE初始化时的内存图和arrayE=arrayD之后的内存图
- 扩展:在Java语言中,所有的引用变量都不需要进行初始化操作,需要进行初始化操作的是该引用变量所引用的对象。
- 基本类型的变量的值存储在栈内存中?这句话其实是错误的。 上面的基本类型数组的内存示意图已经说的很清楚了!
- 所有局部变量都是存放在栈内存中?这句话是正确的。 实际上,不管是基本类型的变量,还是引用类型的变量,都是存放在各自的方法栈区中,但引用类型所引用的对象则总是存放在堆内存中!对于Java而言,堆内存中对象通常是不允许直接访问的,为了访问堆内存中的对象,通常只能通过引用变量。这样可以保证程序更加健壮,如果程序直接访问并修改堆内存中的数据,可能破坏内存中数据的完整性,从而导致程序的Crash。
- 引用类型的变量何时只是栈内存中的变量本身,何时又变为引用实际的Java对象呢?其规则是:引用变量本质是一个指针,只要程序通过引用变量访问属性,或者通过引用变量来调用方法,该引用变量将会由它所引用的对象所替代。如:下面这段程序
public class ArrayTest3{
public static void main(String[] args){
int[] arrayF = null;
// 只要不访问 arrayF 的属性和方法,程序完全可以使用该数组变量
System.out.println(arrayF); // 输出为null
System.out.println(arrayF.length); // 报错:NullPointException
arrayF = new int[5];
// arrayF 指定有效的数组对象后,访问属性或方法才有效
System.out.pringln(arrayF.length);
}
}
基本类型数组的初始化
对于基本类型的数组来说,数组元素的值直接存放在对应的数组元素中,因此基本类型数组的初始化过程比较简单:程序直接先为数组分配存储空间,再将数组元素的值存储在对应的内存区中。
引用类型数组的初始化
对于引用类型的数组来说,数组元素的值依然是一个引用。对下面这段程序来说:
public class ArrayTest4{
public static void main(String[] args){
Person[] persons = new Person[2];
Person one = new Person();
one.name = "zhangsan";
one.age = 21;
Person two = new Person();
two.name = "lisi";
two.age = 22;
persons[0] = one;
persons[0].info();
persons[1] = two;
persons[1].info();
}
}
class Person{
String name;
Integer age;
public void info(){
System.out.println("姓名是:" + this.name + ",年龄是:" + this.age);
}
}
数组元素和数组、多维数组的实质
- 只要在已有数据类型之后加方括号,就会产生一个新的数组类型,如:int —> int[] 在int后加 [] 即变为 int[] 数组类型。
- 只要去掉数组类型之后的 [],就能得到数组元素的类型,如:int[] —> int。
- 多维数组的实质,就是在以后的数组之后,在加 [] 变成一个多维的数组,如:一个三维数组的数组元素类型是二维数组,二维数组的数组元素类型是一维数组…一个 N 维数组的数组元素类型是 N-1 维数组。依据这样的一种推理,也就能理解为什么初始化多维数组时可以只初始化最左边的维数这句话了。
// 定义一个二维数组 arrayG
int[][] arrayG = new int[3][];
感想
最近才发现自己的基础有多薄弱,发觉还是要再去梳理一遍基础!看了一章 ”Java数组与内存控制“ 收获颇丰,尝试着用博客的方式写下来,第一次写,磨了很久,不过加深了对知识点的印象。哈哈,欢迎指正批评!继续加油!
下一篇:对象与内存控制(一)
所谓迷茫,就是你的才华还配不上你的梦想