4.6.3 引用类型数组的初始化
4.6.3 引用类型数组的初始化
引用类型数组的数组元素是引用,因此情况变得更加复杂。每个数组元素里存储的还是引用,它指向另一块内存,这块内存里存储了有效数据。
程序示例 引用类型数组 初始化 示意图
为了更好地说明引用类型数组的运行过程,下面先定义一个Person
类:
1 | class Person { |
下面程序将定义一个Person
数组,接着动态初始化这个Person
数组,并为这个数组的每个数组元素指定值。
1 | public class ReferenceArrayTest { |
上面代码的执行过程代表了引用类型数组初始化的典型过程。下面将结合示意图详细介绍这段代码的执行过程。
执行Person[] students;
代码时,这行代码仅仅在栈内存中定义了一个引用变量,也就是一个指针,这个指针并未指向任何有效的内存区。此时内存中存储示意图如图4.8所示:
在如图4.8所示的栈内存中定义了一个students
变量,它仅仅是一个引用,并未指向任何有效的内存。直到执行初始化,本程序对students
数组执行动态初始化,动态初始化由系统为数组元素分配默认的初始值:null
,即每个数组元素的值都是null
执行动态初始化后的存储示意图如图4.9所示
从图4.9中可以看出,students
数组的两个数组元素都是引用,而且这个引用并未指向任何有效的内存,因此每个数组元素的值都是null
。这意味着依然不能直接使用students
数组元素,因为每个数组元素都是null
,这相当于定义了两个连续的Person
变量,但这个变量还未指向任何有效的内存区,所以这两个连续的Person
变量(students
数组的数组元素)还不能使用。
接着的代码定义了zhang
和lee
两个Person
实例,定义这两个实例实际上分配了4块内存,在栈内存中存储了zhang
和lee
两个引用变量,还在堆内存中存储了两个Person
实例。此时的内存存储示意图如图4.10所示。
此时students
数组的两个数组元素依然是null
,直到程序依次将zhang
赋给students
数组的第一个元素,把lee
赋给students
数组的第二个元素,students
数组的两个数组元素将会指向有效的内存区。此时的内存存储示意图如图4.11所示。
从图4.11中可以看出,此时zhang
和students[0]
指向同一个内存区,而且它们都是引用类型变量,因此通过zhang
和students[0]
来访问Person
实例的实例变量和方法的效果完全一样,不论修改students[0]
所指向的Person
实例的实例变量,还是修改zhang
变量所指向的Person
实例的实例变量,所修改的其实是同一个内存区,所以必然互相影响。同理,lee
和students[1]
也是引用同一个Person
对象,也具有相同的效果。