数组在内存中的存储
public class ArrayTest {
@Test
public void testArrayInRam(){
int[] a = {1,2,3};
int[] b = new int[4];
System.out.println("数组b的长度为:" + b.length);
/*
输出a数组中的元素
结果为:1 2 3
*/
Arrays.stream(a).forEach(System.out::println);
/*
输出b数组中的元素
结果为 0 0 0 0
*/
Arrays.stream(b).forEach(System.out::println);
b = a;
/*
再次输出b数组中的元素
结果为:1 2 3
*/
Arrays.stream(b).forEach(System.out::println);
}
}
程序初始化a、b两个数组时,内存中实际上产生了四块内存区,其中栈内存中有两个引用变量:a与b;堆内存中也有两块内存区,分别存储a、b所指向的数组本身,且a的长度是3,b的长度是4。当执行b = a时,即把a中存储的引用变量赋给b,也就是让b指向a所指向的地址
数组的初始化
基本类型数组的初始化
/**
* 测试基本类型初始化
*/
@Test
public void testPrimitiveArray(){
int [] ints; //在栈内存中定义了一个空引用
ints = new int[5]; // 开始动态初始化,系统分配内存空间以及默认值
// 循环为每个元素中元素依次赋值
for (int i = 0;i < ints.length;i++){
ints[i] = i;
}
引用类型数组的初始化
/**
* 测试引用类型数组初始化
*/
@Test
public void testReferenceArray(){
Apple[] apples; // 在内存中定义了一个空引用
apples = new Apple[2]; // 执行初始化,默认值为null
/*
定义了两个Apple实例,分配了四块内存,在栈内存中存储了huanniu和hongxing两个引用变量
以及在堆内存存储了两个Apple实例
*/
Apple huaniu = new Apple("huanniu","red");
Apple hongxing = new Apple("hongxing","red");
// com.yiqi.test.Array.Apple@58d25a40
System.out.println(huaniu);
// com.yiqi.test.Array.Apple@1b701da1
System.out.println(hongxing);
/*
将huaniu和hongxing分别赋给数组中第一个元素和第二个元素
*/
apples[0] = huaniu;
apples[1] = hongxing;
/*
打印数组中的两个元素
结果是 com.yiqi.test.Array.Apple@383534aa
com.yiqi.test.Array.Apple@6bc168e5
说明赋值后数组中的两个元素分别与两个apple实例指向同一个内存区
*/
Arrays.stream(apples).forEach(System.out::println);
}
关于java多维数组
java中数组类型是引用类型,因此数组变量其实也是一个引用,这个引用指向真实的数组内存。数组元素的类型也可以是引用,如果数组元素的引用再次指向真实的数组内存,就是java中的多维数组。实质上还是一维数组,只是数组元素也是引用且引用指向一堆数组。二维数组的数组元素是一维数组,三维数组的数组元素是二维数组,从这个角度来看,java中并没有多维数组。
语法结构
// 定义
int[][] ints;
// 初始化
ints = new int[2][]
PS.为什么会有栈内存和堆内存之分
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存中,随着方法执行的结束,这个方法的内存栈也将自然销毁。因此,所有在方法中定义的局部变量都是放在栈内存中的;在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便于反复利用(因为对象的成本比较大),这个运行时的数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象话可能被另一个引用变量所引用(例如方法的参数传递),则这个对象依然不会被销毁。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收器才会在合适的时候回收它
网友评论