Java数组与内存控制

Posted ✧*꧁一品堂.技术学习笔记꧂*✧.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java数组与内存控制相关的知识,希望对你有一定的参考价值。

一、Java数组初始化

Java数组是静态的,即当数组被初始化之后,该数组的长度是不可变的。Java数组使用之前必须先对数组对象进行初始化,所谓初始化,就是为数组的所有元素分配内存空间,并为每个数组元素指定初始值。(文章来源于李刚老师的《突破java程序员的16课》)

1:基本类型数组的两种初始化方式

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

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

Java的数组是静态的,一旦数组初始化完成,数组元素的内存空间分配即结束,程序只能改变数组元素的值,而无法改变数组的长度。Java的数组变量是一种引用类型的变量,数组变量并不是数组本身,它只是指向堆内存中的数组对象。因此,可以改变一个数组变量所引用的数组,这样可以造成数组长度可变的假象。

下面由一段程序来说明:

  1 public class ArrayTest {
  2 
  3     public static void main(String[] args) {
  4         //采用静态初始化方式初始化第1个数组
  5         String[] books = new String[]{
  6                 "疯狂java讲义",
  7                 "轻量级Java EE企业级应用实战",
  8                 "疯狂Ajax讲义",
  9                 "疯狂XML讲义"
 10         } ;
 11         //采用静态初始化的简化方式初始化第2个数组
 12         String[] names = {
 13             "孙悟空",
 14             "猪八戒",
 15             "白骨精"
 16         };
 17         //采用动态初始化方式初始化第3个数组
 18         String[] strArr = new String[5];
 19         //测试
 20         System.out.println("第一个数组长度为:"+books.length);
 21         System.out.println("第二个数组长度为:"+names.length);
 22         System.out.println("第三个数组长度为:"+strArr.length);
 23 
 24         //让books数组变量,strArr数组变量指向names所引用的数组
 25         books = names;
 26         strArr = names;
 27         System.out.println("------------------");
 28         System.out.println("books数组长度为:"+books.length);
 29         System.out.println("strArr数组长度为:"+strArr.length);
 30         //改变books数组变量所引用的数组的第二个元素值
 31         books[1] = "唐僧";
 32         System.out.println("names数组的第二个元素为:"+books[1]);
 33     }
 34 }


打印结果为:

  1 第一个数组长度为:4
  2 第二个数组长度为:3
  3 第三个数组长度为:5
  4 ------------------
  5 books数组长度为:3
  6 strArr数组长度为:3
  7 names数组的第二个元素为:唐僧

下图表示的是3个引用变量和数组对象在内存中的分配情况:

image

从图中可以看出,原来books变量所引用的数组长度依然为4,但不再有任何引用变量引用该数组,因此它将会变成垃圾,等待回收机制回收。程序中3个变量同时引用同一个数组对象,因此当执行books[1] = "唐僧";时names数组的第二个数组的值也会改变。

二:数组一定要初始化吗?


  1 ...
  2 int[] nums = new int[]{12,32,34};
  3 //定义另一个数组变量
  4 int[] prices;
  5 //让prices数组指向nums所引用的数组
  6 prices = nums;
  7 ...

执行了上面的代码后,prices变量已经指向有效的内存及一个长度为4的数组对象,程序可以使用prices变量了

三:基本类型数组的初始化

对于基本类型数组而言,数组元素的值直接存储在对应的数组元素中,因此基本类型数组的初始化比较简单:程序直接先为数组分配内存空间,再将数组元素的值存入对应内存里。

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

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

四:引用类型数组的初始化

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

五:使用数组

当数组引用变量指向一个有效的数组对象之后,程序就可以通过该数组引用变量来访问数组对象。Java语言不允许直接访问堆内存中的数据,因此无法直接访问堆内存中的数组对象,程序将通过数组引用变量来访问数组。





注:本文来源于:cnblogs:牛奶、不加糖

以上是关于Java数组与内存控制的主要内容,如果未能解决你的问题,请参考以下文章

Java细节整理——数组与内存控制

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

JAVA对象与内存控制

开销与代码速度(java.io.File 数组与 java.lang.String 数组)

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

Java程序猿之流程控制与数组