java基础 - java数组工作方式

接上篇自己实现java数组 https://blog.csdn.net/qq_37256896/article/details/90045497,但是java数组内部是如何工作的呢,创建一个java数组,jvm都做了些什么呢,这值得我们思量,接下来就从看下面的是具体的细节吧

数组的初始化有以下两种方式。

■ 静态初始化:初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组长度。

■ 动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值。

不要同时使用静态初始化和动态初始化。也就是说,不要在进行数组初始化时,既指定数组的长度,也为每个数组元素分配初始值

Java的数组是静态的,一旦为数组初始化完成,数组元素的内存空间分配即结束,程序只能改变数组元素的值,而无法改变数组的长度。

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

books数组变量原本指向堆内存下面的数组,当执行了books=names;语句之后,books数组将改为指向堆内存中间的数组,而原来books变量所引用的数组的长度依然是4。

 

 

这时候由于没有引用指向堆内存后,但不再有任何引用变量引用该数组,因此它将会变成垃圾,等着垃圾回收机制来回收。

  • java中的数组必须让其初始化,并且为期分配内存,如果真正掌握了Java数组在内存中分配机制,那么完全可以换一个方式来初始化数组,或者说,数组无需经过初始化。

Java的数组变量是引用类型的变量,它并不是数组对象本身,只要让数组变量指向有效的数组对象,程序中即可使用该数组变量

例如:

定义一个prices数组变量
              int] prices;
            //让prices数组指向nums所引用的数组
              prices = nums;
            for (int i=0 ; i < prices.length ; i++)
            {
                    System.out.println(pricesi]);
            }
            //将prices数组的第3个元素赋值为34
            prices2]=34;
            //访问nums数组的第3个元素,将看到输出34
            System.out.println("nums数组的第3个元素的值是:"+nums2]);
          }
      }

常常说使用Java数组之前必须先进行初始化,可是现在prices变量却无需初始化,这不是互相矛盾吗?其实一点都都不矛盾。关键是大部分时候,我们把数组变量和数组对象搞混了,数组变量只是一个引用变量(有点类似于C语言里的指针),通常存放在栈内存中(也可被放入堆内存中的);而数组对象就是保存在堆内存中的连续内存空间。对数组执行初始化,其实并不是对数组变量执行初始化,而是要对数组对象执行初始化—也就是为该数组对象分配一块连续的内存空间,这块连续内存空间的长度就是数组的长度。虽然上面程序中的prices变量看似没有经过初始化,但执行prices=nums;就会让prices变量直接指向一个已经执行初始化的数组。

对于数组变量来说,它并不需要进行所谓的初始化,只要让数组变量指向一个有效的数组对象,程序即可正常使用该数组变量。

提示

对于Java程序中所有的引用变量,它们都不需要经过所谓的初始化操作,需要进行初始化操作的是该引用变量所引用的对象。比如,数组变量不需要进行初始化操作,而数组对象本身需要进行初始化;对象的引用变量也不需要进行初始化,而对象本身才需要进行初始化。

所有局部变量都是放在栈内存里保存的,不管其是基本类型的变量,还是引用类型的变量,都是存储在各自的方法栈区中;但引用类型变量所引用的对象(包括数组、普通Java对象)则总是存储在堆内存中

引用类型变量何时只是栈内存中的变量本身,何时又变为引用实际的Java对象。其实规则很简单:引用变量本质上只是一个指针,只要程序通过引用变量访问属性,或者通过引用变量来调用方法,该引用变量将会由它所引用的对象代替。

public class PrimitiveArrayTest2
      {
            public static void main(String] args)
            {
              //定义一个int]类型的数组变量
              int] iArr=null;
              //只要不访问iArr的属性和方法,程序完全可以使用该数组变量
              System.out.println(iArr);                  //①
              //动态初始化数组,数组长度为5
              iArr=new int5];
              //只有当iArr指向有效的数组对象后,下面才可访问iArr的属性
              System.out.println(iArr.length);            //②
          }
      }

对于①行代码而言,虽然此时的iArr数组变量并未引用到有效的数组对象,但程序在①处并不会出现任何问题,因为此时并未通过iArr访问属性或调用方法,所以系统不会去访问iArr所引用的数组对象。对于②行代码而言,此时程序通过iArr访问了length属性,程序将自动变为访问iArr所引用的数组对象,这就要求iArr必须引用一个有效的对象。

当通过引用变量来访问实例属性,或者调用非静态方法时,如果该引用变量还未引用一个有效的对象,程序就会引发NullPointerException运行时异常。

使用数组:

  • Java语言不允许直接访问堆内存中的数据,因此无法直接访问堆内存中的数组对象,程序将通过数组引用变量来访问数组。
  • Java语言避免直接访问堆内存中的数据可以保证程序更加健壮,如果程序直接访问并修改堆内存中数据,可能破坏内存中的数据完整性,从而导致程序 Crash。
  • main方法声明的变量都属于局部变量,因此它们都被保存在 main方法栈中;但数组元素则作为数组对象的一部分,总是保存在堆内存中,不管它们是基本类型的数组元素,还是引用类型的数组元素
  • 数组的长度:

很多书上都介绍说:通过数组的length 属性可以获取数组的长度,其实这个说法不够准确。更准确的说法是:数组的length 属性应该返回系统为该数组所分配的连续内存空间的长度。

通过以上我们可以更加的深入的了解数组是如何工作的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay三石 [Alay Kay]

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值