Java数组在内存中的存储过程

一、前言

数组引用变量只是一个引用,这个引用变量可以指向任何有效的内存,只有当该引用指向有效内存后,才可以通过该数组变量来访问数组元素.

定义并赋值一个数组时,要把数组看成两部分:
1.数组引用,也就是在代码中定义的数组引用变量;
2.实际的数组对象,这部分是在堆内存里运行的,通常无法直接访问它,只能通过数组引用变量来访问.

二、数组的初始化

两种方式

  • 动态初始化
    数据类型[ ] 数组名 = new 数据类型[长度];
    eg : int[ ] arr = new int[10];

    拆分形式 : int[ ] arr ;
    		  arr = new int[10];
    						
    
  • 静态初始化
    两种形式 :

    1. 数据类型[ ] 数组名 = new 数据类型[ ] {元素1, 元素2, 元素3, ...};
      eg : int[ ] arr = new int[ ]{1, 2, 3, 4};
      拆分形式 : 
      		 int[ ] arr;
      	     arr = new int[ ]{1, 2, 3, 4};
      
    2. 数据类型[ ] 数组名 = {元素1, 元素2, 元素3, ...};(此为上面的简略形式) 不允许拆分
      eg : int[ ] arr = {1, 2, 3, 4};

三、深入数组

3.1 基本类型数组的初始化

初始化数组时,先为该数组分配内存空间,然后直接将数组元素的值存入对应数组元素中.

public class BasicArrayTest {
	public static void main(String[] args) {
		// 定义一个int[]类型的数组变量
		int[] arr;
		// 动态初始化数组,数组长度为5
		arr = new int[5];
		// 采用循环方式为每个数组元素赋值
		for(int i = 0; i < arr.length; i++) {
			arr[i] = i;
		}
	}
}
  1. 执行int[] arr时,仅定义一个数组变量,此时内存中的存储示意图如下:
    int[ ] arr
    仅在栈内存中定义了一个空引用(就是arr数组变量),这个引用并未指向任何有效的内存,故在初始化时无法指定数组的长度,
  2. 执行arr = new int[5];动态初始化后,系统将负责将为该数组分配内存空间,并分配默认的初始值:所有数组元素都被赋值为0,此时内存中的存储示意图如下图:
    arr = new int[5]
  3. 执行循环为该数组的每个数组元素依次赋值后,此时每个数组元素的值都变成程序显示指定的值,显示指定每个数组元素值后的存储示意图如下:
    循环依次赋值
  4. 每个数组元素的值直接存储在对应的内存中.操作基本类型数组的数组元素时,实际上就是操作基本类型的变量.

3.2 引用类型数组的初始化

引用类型数组的数组元素是引用,因此更复杂些.每个数组元素里存储的还是引用,它指向另一块内存,这块内存里存储了有效数据.

定义一个Person类(所有类都是引用类型):

class Person {
	public int age;
	public double height;
	public void info() {
		System.out.println("My age is: " + age + ", My height is: " + height);
	}
}

定义一个Person[]数组,接着动态初始化这个Person[]数组,并未这个数组的每个数组元素指定值.

public class ReferenceArrayTest {
	public static void main(String[] args) {
		// 定义一个students数组变量,其类型是Person[]
		Person[] students;
		// 执行动态初始化
		students = new Person[2];
		// 创建一个Person实例,并将这个Person实例赋给zhang变量
		Person zhang = new Person();
		// 为zhang所引用的Person对象的age,height赋值
		zhang.age = 15;
		zhang.height = 175;
		// 创建一个Person实例,并将这个Person实例赋给li变量
		Person li = new Person();
		// 为li所引用的Person对象的age,height赋值
		li.age = 18;
		li.height = 183;
		// 将zhang变量的值赋给第一个数组元素
		student[0] = zhang;
		// 将li变量的值赋给第二个数组元素
		students[1] = li;
		// 下面两行代码的结果完全一样,因为li和students[1]指向的是同一个Person实例
		li.info();
		students[1].info();
	}
}
  1. 执行Person[] students;,这行代码仅在栈内存中定义了一个引用变量,也就是一个指针,这个指针并未指向任何有效的内存区.此时内存中的存储示意图如下:
    Person[] students
    它仅仅是一个引用,并未指向任何有效的内存.
  2. 执行动态初始化时,students = new Person[2];动态初始化由系统为数组元素分配默认的初始值:null,即每个数组元素的值都是null.执行动态初始化后的存储示意图如下图:
    动态初始化
    每个数组元素的值都是null.这意味着依然不能直接使用students数组元素,因为每个数组元素都是null,顶一个两个连续的Person变量,但这个变量还未指向任何有效的内存区.
  3. 接着定义了zhang和li两个Person实例,定义这两个实例实际上分配了4块内存,在栈内存中存储了zhang和li两个引用变量,还在堆内存中存储了两个Person实例.此时内存存储示意图如下:
    定义zhang和li两个Person实例
  4. 将zhang赋给students数组的第一个元素,把li赋给students数组的第二个元素,students数组的两个数组元素将会指向有效的内存区.此时的内存存储示意图如下:
    将两个实例赋给students数组
  5. 此时zhang和students[0]指向同一个内存区,而且它们都是引用类型变量,因此通过zhang和students[0]来访问Person实例的Field和方法的效果完全一样,不论修改students[0]还是zhang变量所指向的Person实例的Field,所修改的其实是同一个内存区,所以必然相互影响.




参考文献:<疯狂java讲义精粹_李刚编著>

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值