第5章_数组

1. 一维数组内存分析

1.1 Java虚拟机的内存划分

为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
JVM架构-简图.png

  1. Java虚拟机最先接触的就是字节码文件class file
  2. 有了类加载文件以后 类加载器子系统就把class文件加载到内存了 在反射的时候会讲
  3. 分配到内存区域 - 运行时数据区
    1. 运行数据区分为几个部分?
      1. 程序计数器
      2. 本地方法栈
      3. 虚拟机栈
      4. 方法区
区域名称作用
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。
堆内存存储对象(包括数组对象),new来创建的,都存储在堆内存。
方法区存储已被虚拟机加载的类信息、常量、(静态变量)、即时编译器编译后的代码等数据。
本地方法栈当程序中调用了native的本地方法时,本地方法执行期间的内存区域
程序计数器程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址

与目前数组相关的内存结构,比如int[] arr = new int[] {1,2,3}

  1. 虚拟机栈:用于存放方法中声明的变量,比如:arr
  2. 堆:用于存放数组的实体:即数组中所有的元素,比如:{1,2,3}

image.png

  1. 第一行代码
    1. 先在栈中存放arr1,在堆内存空间开辟一个连续4个的空间,并且对外只暴露首地址值 0x12ab
    2. 栈中arr1变量的值放的是首地址值 0x12ab,此时就构成了一个指针,指向堆内存中这个数组的首位置
    3. 给int数组默认值 0,0,0,0
  2. 第二三行,给下标0和2的数组元素赋值
  3. 第四行代码
    1. 先在栈中存放arr2,在堆内存空间开辟一个连续2个的空间,并且对外只暴露首地址值 0xaabb
    2. 栈中arr2变量的值放的是首地址值 0xaabb,此时就构成了一个指针,指向堆内存中这个数组的首位置
    3. 给String数组默认值 null,null
  4. 第五行代码
    1. 暂且放到后面讲 涉及常量池
  5. 第六行代码
    1. 重新开辟空间,长度为3的连续空间0x12cd
    2. arr2变量存放的值为0x12cd,原来的不要了
    3. 给String数组默认值 null,null,null
    4. 堆空间中0xaabb就成了垃圾,被GC回收
  6. 整个main方法结束了,弹栈,里面的arr1和arr2也不存在了,栈桢也不存在,堆内存的内容也不存在,垃圾回收

image.png
将arr的地址值赋给arr1
只要出现new,就会在堆空间中开辟新的内存,否则不会
一维数组的练习,见Gitee

2.二维数组

String[][] grade = new String[][]{{"段誉","令狐冲"},{"张三丰","周芷若"},{"赵敏","张无忌","韦小宝","杨过"}};

2.1 声明与初始化

2.1.1 静态初始化

int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
定义一个名称为arr的二维数组,二维数组中有三个一维数组

  • 每一个一维数组中具体元素也都已初始化
    • 第一个一维数组 arr[0] = {3,8,2};
    • 第二个一维数组 arr[1] = {2,7};
    • 第三个一维数组 arr[2] = {9,0,1,6};
  • 第三个一维数组的长度表示方式:arr[2].length;
  • 注意特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。
int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10}};//声明与初始化必须在一句完成

int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}};

int[][] arr;
arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}};

arr = new int[3][3]{{1,2,3},{4,5,6},{7,8,9,10}};//错误,静态初始化右边new 数据类型[][]中不能写数字

2.1.2 动态初始化

2.1.2.1 格式1:规则二维表:每一行的列数是相同的

int[][] arr = new int[3][2];

  • 定义了名称为arr的二维数组
  • 二维数组中有3个一维数组
  • 每一个一维数组中有2个元素
  • 一维数组的名称分别为arr[0], arr[1], arr[2]
  • 给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
2.1.2.2 格式2:不规则:每一行的列数不一样

(1)先确定总行数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][];
(2)再确定每一行的列数,创建每一行的一维数组
二维数组名[行下标] = new 元素的数据类型[该行的总列数];

int[][] arr = new int[3][];

  • 二维数组中有3个一维数组。
  • 每个一维数组都是默认初始化值null (注意:区别于格式1)
  • 可以对这个三个一维数组分别进行初始化:arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2];
  • 注:int[][]arr = new int[][3]; //非法

2.1.3 数组元素的默认初始化值

动态初始化方式1

int[][] arr = new int[3][4]
外层元素:默认存储地址值
内层元素:默认与一维数组元素的不同类型的默认值规定相同

  • int数组元素默认初始值:0
  • 浮点型数组元素默认初始值:0.0
  • char数组元素默认初始值:0
  • boolean数组元素默认初始值:false
  • 引用型数组元素默认初始值:null
int[][] arr = new int[3][2];
// 外层元素默认值:
System.out.println(arr[0]); // 地址值,只想了一个一维数组
System.out.println(arr[1]);
// 内层元素默认值:
System.out.println(arr[0][0]); // 0 因为是int类型

-----------------------------------------------------------------
boolean[][] arr1 = new boolean[3][4];
// 外层元素默认值:
System.out.println(arr1[0]); // 地址值,只想了一个一维数组
// 内层元素默认值:
System.out.println(arr1[0][1]); // false

-----------------------------------------------------------------
String[][] arr2 = new String[4][2];
// 外层元素默认值:
System.out.println(arr2[0]); // 地址值,只想了一个一维数组
// 内层元素默认值:
System.out.println(arr2[0][1]); // null;

-----------------------------------------------------------------

动态初始化方式2

int[][] arr = new int[3][]
外层元素:默认存储null,因为数组是引用类型
内层元素:空指针异常

int[][] arr = new int[4][];
// 外层元素默认值:
System.out.println(arr[0]); // null
// 内层元素默认值:
System.out.println(arr[0][0]); // 报错空指针;没有数组

2.2 二维数组内存解析

image.png
image.png

  1. arr1指向一个一维数组,地址值为0xaabb,在arr1变量内保存
  2. arr2[2][2]里面没有数组,所以报错空指针

image.png

  1. arr1第二个[]写了就是地址值,没写就是null
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值