关于数组,我们首先要知道的是,他是引用数据类型,数组是存储同一种数据类型多个元素的容器。数组既可以存储基本数据类型,也可以存储引用数据类型。数组有两种初始化方式,动态初始化和静态初始化.以下通过介绍两种初始化方式来介绍内存的分配.
在介绍内存分配前,首先要对内存有一定的了解:
内存,简单说就是存放正在运行的程序,我们知道,java程序运行的载体是JVM,运行环境是JRE,内存分配给JVM空间执行程序,然后JVM又把内存划分了几个板块,分别是:
栈内存:这个内存是动态的,我们可以在栈内存中看到程序的执行流程(包括方法的执行和死亡),当有方法被调用,就会有方法进入栈内存中.注意,因为栈的特性,方法执行流程是先进后出;同时,栈内存也存放局部变量,使用完毕就会被垃圾回收.
堆内存:这个里面只保存new出来的东西,其本质是对象的实体.比如,你创建了一个数组对象A------>int[] A = new int[5];真正的实体不是左边的A,真正对象的实体是new出来的东西.
关于堆中的元素(new出的对象)的特点:
A.每一个对象都有一个唯一的地址值
B.每一个对象的数据都有默认值,系统根据数据类型给予
整型:0
浮点型:0.0
字符型:'\u0000'
布尔型:false
引用数据类型:null
C.堆中的数据使用完毕不会立即回收,在垃圾回收机制空闲的时候回收
方法区:保存字节码文件,也就是.class文件.还有就是常量池.
本地方法区:用来存储java代码和Windows系统交互的方法.
寄存器:跟cpu相关,这里不做过多介绍.
讲一下这张图,首先左边的代码到内存后,先到了方法区,当执行到main方法时,main方法从上到下压进栈,给main方法分配一定的空间.接着,我们new一个int类型名字是arr的数组对象.那么,堆内存中会分配一块空间,来初始化这个对象,并有唯一的一个地址值对应这个对象,在栈内存中,会在main方法里分配一块空间,存放数组名 arr,以及new出对象的堆内存地址.
在进行赋值时,比如 arr[0] = 100,赋值过程如下:
在栈内存中通过arr这个数组名,得到一个地址,我们拿着这个地址到堆内存中,找这个地址对应的内存块,根据索引0,找到这块空间,把默认值替换掉.
我们可以看到每个new出来的对象地址是不同的,这也就解释了下面的代码:
public class TestDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] A1 = new int[2];
A1[0]=10;
System.out.println("A1的地址是0"+A1);
System.out.println("现在A1的值是:"+A1[0]);
int[] A2 = A1; //A1的地址传给了A2
A2[0] =20; //给A2[0]赋值
System.out.println("A1的地址是0"+A1);
System.out.println("A2的地址是0"+A2);
System.out.println("现在A1的值是:"+A1[0]+"\tA2的值是:"+A2[0]);
}
}
运行结果:
A1的地址是0[I@1d7fbfb
现在A1的值是:10
A1的地址是0[I@1d7fbfb
A2的地址是0[I@1d7fbfb
现在A1的值是:20 A2的值是:20
关于静态初始化内存的分配,就是就是通过栈内存中arr对应的地址,到堆内存中,根据数组索引,把数组的默认值改掉.
下面是代码实现:
public class TestDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = { 1, 2, 3, 4, 5, 6 };
int temp;
//联动for循环
for (int star = 0, end = a.length - 1; star <= end; star++, end--) {
temp = a[star];
a[star] = a[end];
a[end] = temp;
}
System.out.print("arry["); //优美的输出数组的内容
for (int i = 0; i < a.length; i++) {
if (i == a.length - 1) {
System.out.println(a[i] + "]");
} else {
System.out.print(a[i] + ", ");
}
}
}
}
这里用到了常量池,在定义变量时,栈内存里存的是常量池中常量对应的地址,对于int b = a,这样的赋值,只是把b指向跟a相同的常量地址,在改变b的常量时,改变的时b指向的常量池的地址,a不会受到改变.