Java jvm、jmm

数组及内存管理

2017-03-11  本文已影响334人  起个名忒难

引言

小明参加面试:
面试官冷着一张脸,推门进来,看了一眼简历,便没有在翻开。
问:在Java中,声明并创建数组的过程,内存是如何分配的?
。。。
问:Java创建数组的方式共有哪几种能说一下吗?
。。。
问:基本类型数组和引用类型数组之间,在初始化的内存分配机制有什么区别吗?
。。。
小明,狼狈逃窜,挥一挥衣袖,没有带走一点尘土,并下定决心要刻苦修炼,等他再出山定要喝着雪花勇闯天涯 。

好了,言归正传,好像有点跑题了。

数组定义
数组相同类型的数据集合,称之为数组。数组一旦初始化,内存空间 、长度就不可变。

数组初始化

type[] arrayName = { v1 ,v2,v3,v4,v5}
type[] arrayName = new type[]{v1,v2,v3,v4,v5}
type[] arrayName = new type[length]

以上就是数组初始化的三种方式,不论哪种初始化方式,一旦初始化完成,数组的空间大小,和数组长度就不会再发生改变 ,允许使用length ,来访问数组的长度。

下面定义一个String类型的数组:

String[] str = {"zhangsan" ,"lisi" ,"wangwu"} ;
String[] str = new String[]{"zhang" ,"li" , "wang"};

String[] str = new String[3] ;

上面代码的内存分配示意图,如下所示:

数组在内存中的存储方式.png

数组是一种引用数据类型,数组引用变量只是一个引用,数组元素和数组变量是在内存里分开存放的。数组元素存放在堆内存中,数组变量存放在栈内存。每个方法执行时,都会建立自己的内存栈,方法结束后,内存栈销毁,数组元素存放在堆内存,方法结束后,不会被销毁,可以被其他的变量引用。

基本类型的数组初始化

对于基本类型而言,数组元素中的值直接存储在对应的数组元素中。

int[] a  ;
a = new int[3] ;
for(int i = 0 ; i<a.length , i++){
    a[i] = i+1 ;
}

分步骤看一下,上面代码,在内存中的初始化过程:


int[] a .png

执行第一行代码,仅在栈内存中创建了一个数组类型的引用变量,并没有指向任何有效的内存。


a = new int[3].png
第二行代码动态的初始化数组,在内存中分配了数组元素的内存空间,并分配了数组的默认值0。a 的引用地址指向了内存地址。
a[i] = i+1.png

循环为数组元素赋值,变为程序员显示指定的值,此时数组的初始化完成。

引用类型数组的初始化
既然是引用类型的数组,必然需要一个class类,来创建类的实例,定义一个person类,code 如下:

public class Person {
    private String name ;
    private int age ;

    public Person(String name , int age ){
        this.name = name ;
        this.age = age ;
    }

    //省略getter和setter方法
}

类有了,来创建存放对象的数组,完成引用类型数组的创建工作

//定义两个Person对象,p1 ,p2
Person p1 = new Person("zhangsan" , 18) ;
Person p2 = new Person("lisi" ,20) ;

//创建Person类型的数组
Person[] p = new Person[2] ;
p[0] = p1 ;
p[1] = p2

内存中创建过程如下:


Person对象的创建.png

上图是创建Person实例的过程,在栈内存中储存了两个引用变量,在堆内存中创建了Person实例。

创建Person类型数组.png

上图是创建数组的过程,在栈内存中存储了数组的引用变量,系统为数组分配了内存空间,并赋初始值null。

数组赋值.png

上图可以看出数组内存放了对象实例的引用地址,p[0] 和p2 指向了一块相同的内存空间,因此通过p[0] 和 p2 操作对象的效果是一样的。

总结
创建数组有3中方式,2中静态创建方式,需要程序员显示为数组赋初值,1种动态创建方式,有系统为数组赋值,数组将引用变量存放在栈内存中,数组元素存放在堆内存中。引用类型数组和基本类型数组的不同之处是,引用类型数组元素中存放的也是引用,而基本类型数组元素中存放的是值。

没有多维数组
JAVA中没有多维数组,既然数组元素可以存放引用地址,那么多维数组可以理解为数组元素存放的值就是另一个数组元素的地址,通过这种方式来组成数组。 下面来看一个简单的Code:

int[][] a = new int[][]{{1,2,3} ,{4} ,{5 ,6,7,8}} ;
for (int i = 0 ; i < a.length ; i++){
    for (int j = 0 ; j< a[i].length ; j++){
         System.out.print(a[i][j] + " ");
    }
    System.out.println();
}
------------结果--------

1 2 3 
4 
5 6 7 8 

一次来类推,三维数组其实是数组的引用的引用构成了三维数组。


少年听雨歌楼上,红烛昏罗帐。  
壮年听雨客舟中,江阔云低,断雁叫西风。
感谢支持!
                                        ---起个名忒难

上一篇下一篇

猜你喜欢

热点阅读