Java数组详谈——从内存角度解析数组

要点概览
1. 初识数组:数组的定义及初始化
2. 深入数组:内存中的数组

一、初识数组: java中的数组与类和接口一样是一种引用类型,数组中只能存放同类型的数据。

首先我们从简单的说起,看看如何定义数组以及定义的方式。
1.数组的定义
a. 中括号在类型后面:Type[] arr;,这是常用也是推荐的数组定义方式:可读性强
b.中括号在引用变量后面:Type arr[];,这种方式是C语言中的数组定义方式,相对前者而言容易引起混淆。

在数组定义后,数组变量arr并未指向任何有效内存。因此在作为类成员变量时,系统会给arr默认值为null;在局部变量中则需要将arr显式初始化后才能使用,否则会报NullPointException。我们结合内存图来理解:
这里写图片描述
2.数组的初始化:初始化后的数组长度就无法再被改变
a.动态初始化数组,长度由变量或者数值决定:arr = new Type[length];
动态初始化后的数组中的元素值:基本数据类型数组元素的默认值为基本数据类型对应的默认值(比如int默认为0),引用数据类型则默认为null。
b.静态初始化数组:
arr = new Type[] {elem1,elem2,elem3.....};
简化后的方式:arr = {elem1,elem2,elem3.....};
注意:错误的初始化方式arr = new Type[length] {elem1,elem2,elem3......};这种方式动态与静态初始化混淆使用。
下面给出初始化后的数组内存图:
这里写图片描述

此时,系统为初始化后的数组分配指向内存,引用变量arr只是一个封装了内存地址值的变量。真正存储数据的是堆内存中的有效内存区。

二、深入数组:
a.栈内存中的数组变量与堆内存中的数组有效存储区
b.基本类型数组的初始化与引用类型数组的初始化及其存储的数据类型分析
c.二维数组与多维数组

1.栈内存中的数组引用变量与堆内存中的数组有效存储区
先看代码:Type[] arr = new Type[] {elem1,elem2,elem3};
定义并完成初始化后,系统在内存中分配了两个空间:一个是在栈内存中为引用变量arr分配空间,一个是在堆内存中为存储区分配空间。如图所示:
这里写图片描述

2.基本类型数组的初始化与引用类型数组的初始化及其存储的数据类型分析
直接上图吧!
基本数据类型数组初始化内存图,以int[] arr = {1,2,3};为例:
这里写图片描述

引用数据类型数组初始化内存图,以String[] arr = {"A","B","C"};为例:
这里写图片描述

二者的异同显而易见吧!基本数据类型数组存储的元素是基本类型的值,也就是说可以直接操纵数组元素;而引用数据类型数组存储的元素实际上是引用变量,然后引用变量指向对应的内存区。那么,如果想要修改引用数组元素数据就要通过引用变量访问对应的内存区去修改数据。

3.二维数组与多维数组
先抛出两个问题:到底有没有二维数组或者多维数组的概念?二维或多维数组是一维数组么?

实际上,所谓的二维数组可以简单的理解成这个一维数组的元素类型为一维数组类型。说的再多不如直接上代码:

二维数组的定义与一维数组定义方式类似,此处不多说。具体看看二维数组的初始化:直接以引用类型数组为例,理解了引用类型数组的内存分配后对于基本类型数组也就小菜一叠了。

//首先提供一个Person类
class Person {
    private String name;

    public Person() {}
    public Person(String name) {
        this.name = name;
    }
}
//定义一个二维数组
Person[][] perArr;

//初始化二维数组————方式一:动态初始化
perArr = new Person[3][2];//3行,2列
for(int i = 0; i < 3; i++)
    for(int j = 0; j < 2; j++)
        perArr[i][j] = new Person("9527");

perArr = new Person[3][];//3行,n列,n是一个可变数
perArr[0] = {new Person(),new Person("Tom"),new Person("Hellon")};
perArr[1] = {new Person("Jim"),new Person("Kellon")};
perArr[2] = {new Person("Kaven"),new Person("Sam"),new Person("Cell"),new Person("Johny")};

//初始化二维数组————方式一:静态初始化
perArr = new Person[3][] {{},{new Person("Kate"),new Person("Steven")},{new Person("Tom"),new Person("Curry"),new Person("Green")}};//3行n列,n可变
//可以简化为
perArr = {{},{new Person("Kate"),new Person("Steven")},{new Person("Tom"),new Person("Curry"),new Person("Green")}};

现在来看内存图,内存图在此只提供

perArr = {{},
{new Person("Kate"),new Person("Steven")},
{new Person("Tom"),new Person("Curry"),new Person("Green")}
};
的内存图:
这里写图片描述

Person perArr = new Person[m][n];

这个二维数组为m行n列,如果访问数组的实例变量length,则有perArr.length = m;由此可知,在二维数组的初始化过程中行数是必须要设置具体的值的。那么,现在我们回到最初的两个问题。二维数组实质上就是一个一维数组,多维数组也是如此。(如果还不懂,请在看一遍内存图)

献此拙文——如有错误或不足,欢迎留言指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值