您的位置:首页 > 其它

数组及其内存管理

2017-10-18 00:00 204 查看
摘要: java

程序需要多个类型相同的变量时可以考虑用数组。

java 数组是引用类型的变量(具有java引用变量的特征)

1.java数组是静态的

当数组被初始化后,该数组占用的内存空间,数组长度都是不可变的。java数组必须初始化才能使用(即创建实际的数组对象,在内存中为数组对象分配内存空间,并为每个数组元素指定初始值)

初始化方式(两种):

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

如:int [] score = new int[]{99,89,79,69,59}; 另一种写法: int [] score = {99,89,79,69,59};

对于静态初始化方式,无需指定长度,指定数组元素,由系统来决定数组的长度。

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

如:int [] score = new int[5];

对于动态初始化方式,只需指定长度(即为每个数组元素指定所需的内存空间)系统将负责为这些元素分配初始值。指定初始值时有以下规则:

数组元素是基本类型的整型(byte,short, int,lang),则数组元素的值是0;

数组元素是基本类型的浮点型(float,double),则数组元素的值是0.0;

数组元素是基本类型的布尔型(boolean),则数组元素的值是false;

数组元素是基本类型的字符型(char),则数组元素的值是‘\u0000’;

数组元素是基本类型的引用类型(String,类,接口,数组),则数组元素的值是null;

不论采用哪种方式初始化数组,一旦初始化完成,该数组的长度(score.length)就不可改变。不要同时使用静态初始化和动态初始化。

java数组是静态的,一旦数组初始化完成,数组元素的内存空间分配即结束,程序只能该改变数组元素的值,无法改变数组长度。
javaScript这种动态语言的数组长度是可以动态改变的。

var arr = [];

document.writeln(“arr的长度是:”+arr.length);

arr[2] = 1;

arr[4] = 4;

document.writeln("arr的长度是:"+arr.length);

第一次输出为0,第二次输出为5;先定义一个名为arr的空数组,它的长度是0,然后为arr数组的第三个,第五个元素赋值时,数组长度变成了5。

Java 数组是一种引用类型的变量,数组变量并不是数组本身,它只是指向堆内存中的数组对象,因此可以改变一个数组变量所引用的堆内存中的数组,这样就可以造成数组长度可变的假象。其实变化的是数组变量,而不是该数组变量所指向的内存。如果没有任何变量引用堆中的数组,它就会变成垃圾,等待垃圾回收机制回收。

数组对象和数组变量:

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

如:int [ ] nums = {1,2,3,4,5};

//声明一个prices 数组。

int [] prices;

//让prices数组指向nums所引用的数组。

prices = nums;

System.out.print(prices.lentgh);

结果为5.

数组变量和数组对象:

7fe0
数组变量类似于C语言中的指针,只是一个引用变量。

数组变量,并不需要所谓的初始化,只要让数组变量指向一个有效的数组对象(堆内存中连续的内存空间),程序即可正常使用该数组变量。

数组对象就是保存在堆内存中的连续内存空间。

数组执行初始化,其实并不是对数组变量执行初始化,而是在堆内存中创建数组对象(在堆内存中分配一块连续的内存空间,内存空间的长度就是数组元素的个数)。

java 程序中的引用变量不需要经过初始化操作,需要进行初始化的是引用变量所引用的对象(堆内存中的空间)。

基本类型数组的初始化:

数组元素的值直接存储在对应的数组元素中,如:int [] score = {99,89,79,69,59};程序直接先为数组分配内存空间,再将数组元素的值存入对应的内存里。

程序运行过程中的“变量”,可以把它理解为一种容器,瓶子用于存储水,而变量用于存储值,也就是数据。

指定类型的瓶子装指定的水,指定类型的变量只能存储指定类型的值。

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

java 中,堆内存中的对象是不允许直接访问的,只能通过引用变量访问堆内存中的对象。

如:int [] score = {1,2,3,4,5};本质上是main栈区的引用变量int [] score,但是使用score.length, score[1]时,系统会自动变为访问堆内存中的数组对象。

究竟何时引用类的变量只是栈内存中的变量本身,何时又变成了引用实际的java对象。规则如下:引用变量本质上只是一个指针,只要程序通过引用变量访问属性,或者通过引用变量来调取方法,该引用变量就会被它的引用的对象替代。

这也是常常会犯的错误(NullPointException);当通过引用变量来访问实例属性,或者调用非静态方法时,如果该引用变量还未引用一个有效的对象(堆内存中的空间),程序就会报空指针异常。

引用类型数组的初始化:

引用类型数组的数组元素依然是引用类型的,因此数组元素里存储的还是引用(指向堆内存中的一块内存,这块内存里存储了该引用变量所引用的对象(包括数组和java对象(堆内存的空间))),对于引用类型的数组而言,它的数组元素其实就是一个引用类型的变量,因此可以指向任何有效(强类型的约束)的内存。

使用数组:

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

这样做的目的是为了保证程序更加健壮,如果程序直接访问并修改堆内存中数据,可能会破坏内存中的数据完整性,从而导致程序crash。

数组元素就是变量:只要在已有数据类型之后增加[]符号,就会产生一个新的数组类型,

如:

int int[] int类型变成了int[]数组类型

Student Student[] Student类型变成了Student[]数组类型

int[] int[][] int[]类型变成了int[][]数组类型

当程序需要多个类型相同的变量来保存程序状态时,可以考虑使用数组来保存这些变量。当一个数组初始化完成之后,就相当于定义了多个类型相同的变量。

无论哪种类型的数组,其数组元素其实相当于一个普通变量,把数组类型去掉一组[]后得到的类型就是该数组元素的类型。

如:

int [] 数组元素是int 类型的变量

Student[]数组元素是Student类型的变量

int[][] 数组元素是int[]类型的变量。

当通过索引来使用数组元素时,将该数组元素当成普通变量使用即可,包括访问该数组元素的值,为数组元素赋值等。

没有多维数组

前面已经指出,只要在已有数据类型之后增加方括号,就会产生一个新的数组类型,如果是int ,增加[] 就是int[] 这个数组类型,如果再以int[] 为已有类型,增加[] 就得到int[][] 类型,依然是数组类型,如果再以int[][]类型为已有类型,增加方括号就得到int[][][]类型,依然是数组类型。

反过来,将数组类型最后一组[] 去掉就得到了数组元素的类型。对于int[][][] 类型的数组,数组元素就是int[][],数组元素就是int[]类型的变量,对于int[] 类型的数组,数组元素就相当于int类型的变量。

上面也是多维数组处理的逻辑,所谓的多维数组(n)就是由n-1维数组对象组成的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: