javaSE学习15_引用类型数组的初始化
2017-04-09 11:23
169 查看
引用类型数组的初始化
引用类型数组的数组元素是引用,因此情况变得更加复杂:每个数组元素里存储还是引用,它指向另一块内存,这块内存里存储了有效数据。
为了更好地说明引用类型数组的运行过程,下面先定义一个Person类(所有类都是引用类型),关于定义类、对象和引用的详细介绍请参考第5章的介绍。Person类的代码如下:
程序清单:codes/04/4-6/Person.java
public class Person
{
//年龄
public int age;
//身高
public double height;
//定义一个info方法
public void info()
{
System.out.println("我的年龄是:" + age + ",我的身高是:" + height);
}
}
下面程序将定义一个Person[]数组,接着动态初始化这个Person[]数组,并为这个数组的每个数组元素指定值。程序代码如下:
程序清单:codes/04/4-6/TestReferenceArray.java
public class TestReferenceArray
{
public static void main(String[] args)
{
//定义一个students数组变量,其类型是Person[]
Person[] students;
//执行动态初始化
students = new Person[2];
//创建一个Person实例,并将这个Person实例赋给zhang变量
Person zhang = new Person();
//为zhang所引用的Person对象的属性赋值
zhang.age = 15;
zhang.height = 158;
//创建一个Person实例,并将这个Person实例赋给lee变量
Person lee = new Person();
//为lee所引用的Person对象的属性赋值
lee.age = 16;
lee.height = 161;
//将zhang变量的值赋给第一个数组元素
students[0] = zhang;
//将lee变量的值赋给第二个数组元素
students[1] = lee;
//下面两行代码的结果完全一样,因为lee和students[1]指向的是同一个Person实例。
lee.info();
students[1].info();
}
}
上面代码的执行过程代表了引用类型数组的初始化的典型过程,下面将结合示意图详细介绍这段代码的执行过程。
执行Person[] students;代码时,这行代码仅仅在栈内存中定义了一个引用变量,也就是一个指针,这个指针并未指向任何有效的内存区。此时内存中存储示意如图4.8所示:
图4.8 定义一个students数组变量后的存储示意
在图4.8中的栈内存中定义了一个students变量,它仅仅是一个引用,并未指向任何有效的内存。直到执行初始化,本程序对students数组执行动态初始化,动态初始化由系统为数组元素分配默认的初始值:null,即每个数组元素的值都是null,执行动态初始化后的存储示意如图4.9所示:
图4.9 动态初始化students数组后的存储示意
从图4.9中可以看出,students数组的两个数组元素都是引用,而且这个引用并未指向任何有效的内存,因此每个数组元素的值都是null.这意味着依然不能直接使用students数组元素,因为每个数组元素都是null,这相当于定义了两个连续的Person变量,但这个变量还未指向任何有效的内存区,所以这两个连续的Person变量(students数组的数组元素)还不能使用。
接着的代码定义了zhang和lee两个Person实例,定义这两个实例实际上分配了4块内存,在栈内存中存储了zhang和lee两个引用变量,还在堆内存中存储了两个Person实例。此时的内存存储示意如图4.10所示:
图4.10 创建两个Person实例后的存储示意
此时students数组的两个数组元素依然是null,直到程序依次将zhang赋给students数组的第一个元素,把lee赋给students数组的第二个元素,students数组的两个数组元素将会指向有效的内存区,此时的内存存储示意如图4.11所示:
图4.11 为数组元素赋值后的存储示意
从图4.11中可以看出:此时zhang和students[0]指向同一个内存区,而且它们都是引用类型变量,因此通过zhang和students[0]来访问Person实例的属性和方法的效果完全一样,不论修改students[0]所指向的Person实例的属性,还是修改zhang变量所指向的Person实例的属性,所修改的其实是同一个内存区,所以必然互相影响。同理,lee和students[1]也是引用到同一个Person对象,也有相同的效果。
转自:http://www.educity.cn/develop/java/201307091131121276.htm
引用类型数组的数组元素是引用,因此情况变得更加复杂:每个数组元素里存储还是引用,它指向另一块内存,这块内存里存储了有效数据。
为了更好地说明引用类型数组的运行过程,下面先定义一个Person类(所有类都是引用类型),关于定义类、对象和引用的详细介绍请参考第5章的介绍。Person类的代码如下:
程序清单:codes/04/4-6/Person.java
public class Person
{
//年龄
public int age;
//身高
public double height;
//定义一个info方法
public void info()
{
System.out.println("我的年龄是:" + age + ",我的身高是:" + height);
}
}
下面程序将定义一个Person[]数组,接着动态初始化这个Person[]数组,并为这个数组的每个数组元素指定值。程序代码如下:
程序清单:codes/04/4-6/TestReferenceArray.java
public class TestReferenceArray
{
public static void main(String[] args)
{
//定义一个students数组变量,其类型是Person[]
Person[] students;
//执行动态初始化
students = new Person[2];
//创建一个Person实例,并将这个Person实例赋给zhang变量
Person zhang = new Person();
//为zhang所引用的Person对象的属性赋值
zhang.age = 15;
zhang.height = 158;
//创建一个Person实例,并将这个Person实例赋给lee变量
Person lee = new Person();
//为lee所引用的Person对象的属性赋值
lee.age = 16;
lee.height = 161;
//将zhang变量的值赋给第一个数组元素
students[0] = zhang;
//将lee变量的值赋给第二个数组元素
students[1] = lee;
//下面两行代码的结果完全一样,因为lee和students[1]指向的是同一个Person实例。
lee.info();
students[1].info();
}
}
上面代码的执行过程代表了引用类型数组的初始化的典型过程,下面将结合示意图详细介绍这段代码的执行过程。
执行Person[] students;代码时,这行代码仅仅在栈内存中定义了一个引用变量,也就是一个指针,这个指针并未指向任何有效的内存区。此时内存中存储示意如图4.8所示:
图4.8 定义一个students数组变量后的存储示意
在图4.8中的栈内存中定义了一个students变量,它仅仅是一个引用,并未指向任何有效的内存。直到执行初始化,本程序对students数组执行动态初始化,动态初始化由系统为数组元素分配默认的初始值:null,即每个数组元素的值都是null,执行动态初始化后的存储示意如图4.9所示:
图4.9 动态初始化students数组后的存储示意
从图4.9中可以看出,students数组的两个数组元素都是引用,而且这个引用并未指向任何有效的内存,因此每个数组元素的值都是null.这意味着依然不能直接使用students数组元素,因为每个数组元素都是null,这相当于定义了两个连续的Person变量,但这个变量还未指向任何有效的内存区,所以这两个连续的Person变量(students数组的数组元素)还不能使用。
接着的代码定义了zhang和lee两个Person实例,定义这两个实例实际上分配了4块内存,在栈内存中存储了zhang和lee两个引用变量,还在堆内存中存储了两个Person实例。此时的内存存储示意如图4.10所示:
图4.10 创建两个Person实例后的存储示意
此时students数组的两个数组元素依然是null,直到程序依次将zhang赋给students数组的第一个元素,把lee赋给students数组的第二个元素,students数组的两个数组元素将会指向有效的内存区,此时的内存存储示意如图4.11所示:
图4.11 为数组元素赋值后的存储示意
从图4.11中可以看出:此时zhang和students[0]指向同一个内存区,而且它们都是引用类型变量,因此通过zhang和students[0]来访问Person实例的属性和方法的效果完全一样,不论修改students[0]所指向的Person实例的属性,还是修改zhang变量所指向的Person实例的属性,所修改的其实是同一个内存区,所以必然互相影响。同理,lee和students[1]也是引用到同一个Person对象,也有相同的效果。
转自:http://www.educity.cn/develop/java/201307091131121276.htm
相关文章推荐
- javaSE学习14_基本类型数组的初始化
- 引用类型数组的初始化
- 1.在使用new创建数组后,此时数组还是一个引用数组。 只有再创建新的对象,并把对象赋值给数组引用,到此初始化结束2.什么是引用类型?
- js学习之javascript引用类型object--练习模拟Map和数组去重
- Java学习之数组1(1.数组的声明;2.元素为引用数据类型的数组;3.关于main方法里的String[] args;4.数组排序;5.数3退1 数组算法,(用数组模拟链表);6数组查找之二分法;7数组的拷贝)
- Java学习笔记一:基本语法:类和对象的介绍、数组、引用类型
- JAVA 引用类型数组的初始化
- C语言学习6 :指针的定义,指针类型要合法,指针要初始化,指针做函数参数,数组和指针的通用性,指针+1所代表的空间,void * 指针,交换函数中的指针,数组和字符型指针区别,字符型指针的应用,使用指针完成字符操作函数
- [javase学习笔记]-6.6 基本数据类型参数与引用数据类型参数的传递过程
- C#学习日记15----引用类型 之 string类型用法总结
- 四张內存变化图揭秘引用类型数组的初始化
- Delphi 2010学习笔记(15)---数据类型(变体数组)---2011-01-21
- C语言学习8:malloc返回的void*类型指针不可以做更改,free双重释放,二维数组的初始化和打印,a和a[0]和a[0][0]的区别,数组指针(*p)[3],指针数组*a[10],动态内存分配版约瑟夫环,动态分配版去空格和逗号处理,二级指针与二维数组互用
- (教学思路 C#数组一)认识数组,了解数组类型、学习定义及初始化
- 学习笔记_JavaSE_15_对象数组、Collection、list
- 引用类型数组初始化
- Java学习之旅基础知识篇:数组及引用类型内存分配
- 【java基础】引用类型数组初始化中,setter和getter函数空指针问题
- 在循环中总是显示初始化引用类型的数组
- [javase学习笔记]-6.6 基本数据类型參数与引用数据类型參数的传递过程