Java数组初始化的内存分配

Java数组初始化的内存分配1 Java 数组是静态的 Java 是静态语言 所以 Java 的数组也是静态的 即 数组被初始化后 长度不可变静态初始化 显式指定每个数组元素的初始值 系统决定数组长度 String books newString 疯狂 Java 讲义 ThinkinginJa Java 核心技术卷 String names newString 张三 李四

1.Java数组是静态的

Java是静态语言,所以Java的数组也是静态的,即:数组被初始化后,长度不可变

静态初始化:显式指定每个数组元素的初始值,系统决定数组长度

String[] books = new String[]{"疯狂Java讲义","Thinking in Java","Java核心技术卷"}; String[] names = new String[]{"张三","李四","王五","赵六"};

动态初始化:显式指定数组的长度,系统决定每个数组元素的初始值

String[] strArr = new String[5];

以上两种初始化的内存使用情况如图所示:

Java数组初始化的内存分配

动态初始化数组由系统决定每个数组元素的初始值,遵循以下规则:

  • byte、short、int、long类型的数组的初始值为0
  • float、double类型的数组的初始值为0.0
  • char类型的数组的初始值为'\u0000',表现为空字符'',但要占位
  • boolean类型的数组的初始值为false
  • 引用类型的数组的初始值为null

一旦数组初始化完成,则长度不可改变,以下代码造成了数组初始化后长度可改变的假象:

books = names; strArr = books; System.out.println(books.length); // 4 System.out.println(strArr.length); // 4

Java的数组变量是一种引用类型的变量,数组变量并不是数组本身,它只是指向堆内存中的数组对象,改变一个数组变量所引用的数组,可以造成数组长度可变的假象。

上述代码让books数组变量和strArr数组变量都指向了names数组变量引用的数组,这样做的结果就是让三个数组变量都引用了相同的数组对象。内存图如下:

Java数组初始化的内存分配

而原来strArr和books引用的数组对象的长度不会改变,由于已经没有变量引用它们,它们成为垃圾,等待垃圾回收机制来回收。此时,程序使用strArr、books、和names这三个变量时,将会访问同一个数组对象。

JavaScript是动态语言,其数组的长度可以改变

2. 数组一定要初始化吗?

实际上,懂得了Java数组的内存机制后,我们可以说:数组不是必须初始化,或者说,数组初始化不仅有之前介绍的两种方法,可以完全换一种方法:

int[] nums = new int[]{1, 2, 3, 4, 5}; int[] arr; arr = nums;

3. 基本类型数组的初始化

程序直接先为数组分配内存空间,再将数组元素的值存入对应的内存中。

int [] nums; ① System.out.println(nums); ② nums = new int[]{1, 2, 3, 4}; ③ System.out.println(nums.length); ④

我们来分析①-④步的内存:

① 定义nums数组变量后的存储示意图如下:

Java数组初始化的内存分配

对于②行代码来说没有任何问题,虽然nums变量并未引用到有效的数组对象,但此时并未通过nums变量访问数组对象的方法或属性,所以没有问题。

③ 静态初始化nums数组后的存储示意图如下:

Java数组初始化的内存分配

对于④行代码来说,此时访问了nums数组对象的属性,所以要求nums必须引用一个有效的对象。

当通过引用变量来访问实例属性或者调用非静态方法时,如果该引用变量还未指向有效的对象,程序就会抛出运行时异常:NullPointerException,例如,第二行代码如果为:
System.out.println(nums.length);
就会抛出NullPointerException




误区:基本类型的数据的值存储在栈内存中
实际上,应该是所有的局部变量都保存在栈内存中,不管是基本类型还是引用类型,局部变量都保存在各自的方法栈中

4. 引用类型数组的初始化

引用类型数组的数组元素仍然是引用类型,因此数组元素里存储的还是引用,它指向另一块内存,这块内存里存储了该引用变量所引用的对象,包括数组和Java对象。

下面程序的执行代表了引用类型数组初始化的典型过程:

class Person{ String name; int age; public void info(){ System.out.println("name:" + name + ", age:" + age); } } // 创建两个Person对象 Person p1 = new Person(); p1.name = "张三"; p1.age = 20; Person p2 = new Person(); p2.name = "李四"; p2.age = 30; // 将两个Person对象赋给数组元素 person[0] = p1; person[1] = p2; // 结果一样,p1和person[0]指向同一个对象 p1.info(); person[0].info();

分析内存:

Java数组初始化的内存分配

Java数组初始化的内存分配

Java数组初始化的内存分配

5. 数组元素就是变量

下面程序师范了将数组元素和普通变量相互赋值的情形:

class Cat{ String name; double height; public Cat(String name, double height){ this.name = name; this.height = height; } public void info(){ System.out.println("name:" + name + ", height:" + height); } } public class TestArray { public static void main(String[] args) { int[] a = new int[5]; for(int i=0; i 
  

内存分析:

Java数组初始化的内存分配

Java数组初始化的内存分配

6. 没有多维数组

如下程序示范了多维数组的用法:

public static void main(String[] args) { int[][] a; a = new int[4][]; // 把a当成一维数组,遍历a数组的每个数组元素 for(int i=0; i 
  

内存分析:

Java数组初始化的内存分配

说明:一般我们认为通过数组的length属性可以获取数组的长度,其实这个说法不够准确,例如数组a,它是一个传统的“二维数组”,它的长度好像定义不是很明确,其实,数组的长度指的是数组所分配的连续内存空间的长度,所以说a数组的长度为4.

我们用一个“极端”的程序来更好的理解数组在内存中的分配机制:

public static void main(String[] args) { Object[] objArr1 = new Object[3]; objArr1[1] = new Object[2]; Object[] objArr2 = (Object[]) objArr1[1]; objArr2[1] = new Object[3]; Object[] objArr3 = (Object[]) objArr2[1]; objArr3[1] = new int[5]; int[] iArr = (int[]) objArr3[1]; for(int i=0; i 
  

内存分析:

Java数组初始化的内存分配

Java数组初始化的内存分配

Java数组初始化的内存分配

Java数组初始化的内存分配

Java数组初始化的内存分配

Java数组初始化的内存分配

System.out.println(((int[])((Object[])((Object[])objArr1[1])[1])[1])[2]);

通过以上内存分析不难得出结果为3.

通过上面的分析不难得出,多维数组的本质仍然是一维数组

因为Java是强类型语言,所以上诉代码需要多次强制类型转化,如果用弱类型语言实现会简单很多,比如用JavaScript实现:

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222427.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午3:49
下一篇 2026年3月17日 下午3:50


相关推荐

  • Oracle报错:IO Error: Invalid number format for port number

    Oracle报错:IO Error: Invalid number format for port numberIOError Invalidnumbe

    2026年3月26日
    2
  • K3 官改新手小白配置阿里DDNS 超级详细「建议收藏」

    K3 官改新手小白配置阿里DDNS 超级详细「建议收藏」K3官改新手小白配置阿里DDNS超级详细写的比较仓促,不对之处请指正,这个是写给小白看的,大神勿喷首先介绍一下什么是DDNSDDNS(DynamicDomainNameServer)是动态域名服务的缩写。DDNS是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器…

    2022年6月12日
    45
  • 3D建模场景怎么做?

    3D建模场景怎么做?在开始做3d场景之前,我绘制了一些草图。选好需要的草图后(图01),我用3dsmax从标准几何体开始制作模型,还使用了像lathe,bevel以及unwrapuvw这类的基本修改器。用不同的参数值进行复制(图02)。为了完成这个项目,一些额外的模型也是必须的(图03)。图01图02图03开始制作材质也就意味着有趣的一部分工作开始了。我喜欢用unwrap修改器工作,然后将所有的展开的渲染图全部输入到photoshop软件中,在photoshop中我可以根据…

    2022年6月3日
    48
  • c语言可重入函数_c语言不可重入函数有哪些

    c语言可重入函数_c语言不可重入函数有哪些什么是可重入函数可重入函数指一个可同时被多个任务调用的过程,当一个函数满足下列条件时多为不可重入函数(1)函数中使用了静态的数据结构;(2)函数中使用了malloc()、free()函数;(3)函数汇总调用了标准I/O函数。(如open、read、write、close等系统调用)如何编写可重入函数(1)编写可重入函数时,不应使用static局部变量,应使用auto即缺省…

    2025年6月11日
    7
  • 零基础学Java(1)初识Java程序

    零基础学Java(1)初识Java程序前言就国内来说,Java毫无疑问是后端语言中的No.1没有之一,所以今天我们也来0基础学习Java!!!Java的好处(针对测试工程师)面试加分->涨薪大多数公司服务端用的都是Java,

    2022年8月7日
    6
  • python中的ideavim有什么作用_IdeaVim插件施用技巧

    python中的ideavim有什么作用_IdeaVim插件施用技巧IdeaVim插件使用技巧在IDEAIntellij小技巧和插件一文中简单介绍了一下IdeaVim插件。在这里详细总结一下这个插件在日常编程中的一些常用小技巧。供有兴趣使用这个插件,但对Vim还不十分熟悉的朋友参考。当然基本的hjkl移动光标和几种常见模式等等基本概念就略过不提了。为了确保只包含常用操作,这里提到的技巧都没有从现成文档里抄,而是凭记忆列出(不常用自然就不记得了)。估计会有所遗…

    2026年4月20日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号