一、JVM内存模型
JVM内存模型
JVM内存划分,人为的根据不同内存空间的存储特点以及存储的数据(不是实际就有这样的空间)。
程序计数器:当前线程所执行的字节码的行号指示器。
本地方法栈:为虚拟机使用的native方法服务。
方法区:线程共享的内存区域,存储已被虚拟机加载的类信息、常量、静态变量即时编译器编译后的代码数据等(这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载)。
Java虚拟机栈:简称栈,每个方法被执行的时候都会同时创建一个栈帧用于存储该方法的局部变量、操作栈、动态链接、方法出口等信息。
每当调用一个方法时,创建一个栈帧,存放了当前方法的局部变量,当方法调用完毕,该方法的栈帧就被销毁了。
Java堆:被所有线程共享的一块内存区域,在虚拟机启动时创建。所有的对象实例以及数组都要在堆上分配。
每次使用new关键字,就表示在堆内存中开辟一块新的存储空间。
GC(Garbage Collection),垃圾回收器。
Java的自动垃圾回收机制可以简单理解为,不需要程序员手动的去控制内存的释放。当JVM内存资源不够用的时候,就会自动地去清理堆中无用对象(没有被引用到的对象)所占用的内存空间。
二、数组
1、什么是数组
所谓数组,把具有相同类型的多个常量值有序组织起来的一种数据形式。这些按一定顺序排列的多个数据称为数组。而数组中的每一个常量值称之为数组元素,数组中使用索引来表示元素存放的位置,索引从0开始,步长是1,有点像Excel表格的行号。
2、定义语法
数组的定义语法:
数组元素类型[] 数组名; 如 int[] ages; 另一种方式:int ages[]; 不推荐
理解:
- 可以把int[]看成是一种数据类型——int类型的数组类型。
- int[] 数组可以看出,该数组中的元素类型是int类型的。
- String[] 数组可以看出,该数组中的元素是String类型的。
3、数组的初始化
数组在定义后,必须初始化才能使用。所谓初始化,就是在堆内存中给数组分配存储空间,并为每一个元素赋上初始值,有两种方式:
- 静态初始化;
- 动态初始化;
3.1静态初始化
程序员直接为每一个数组元素设置初始化值,而数组的长度由系统(JVM)决定。
语法:数组元素类型[] 数组名 = new 数组元素类型[]{元素1,元素2,元素3,.......};
int[] nums = new int[]{1,3,5,7,9}; 简单写法: int[] nums = {1,3,5,7,9};//简单写法,定义和初始化必须同时写出来
3.2 动态初始化
程序员只设置数组元素个数,而数组的元素的初始值由系统(JVM)决定。
语法:数组元素类型[] 数组名 = new 数组元素类型[length];
int[] nums = new int[5];
不能同时指定元素值和数组长度,反例如下:
int[] nums = new int[5]{1,3,5,7,9};
不同数据类型的初始值:
图片 55.png
int[] arr1 = new int[3]; int类型数组,每一个元素的初始值为0 double[] arr2 = new double[5]; double类型数组,每一个元素初始值为0.0 String[] arr3 = new String[2]; String类型数组,每一个元素的初始值为null
4、数组的遍历
int[] nums = new int[] { 1, 3, 5, 7 }; for (int index = 0; index < nums.length; index++) { int ele = nums[index];//index依次是 0、1、2、3 System.out.println(ele); }
使用for-each(增强for循环)操作数组
for(数组元素类型 变量: 数组){ //TODO }
使用for-each操作数组更简单,因为可以不关心索引,其底层原理依然是上述的for循环操作数组。
int[] nums = new int[] { 1, 3, 5, 7 }; for (int ele : nums) { System.out.println(ele); }
三、二维数组
1、二维数组的定义和初始化
定义和静态初始化一维数组的语法:
数组元素类型[] 数组名 = new 数组元素类型[]{值1,值2,值3,...};如:
int[] nums = new int[]{1,3,5,7};
定义和静态初始化二维数组的语法:
数组元素类型[][] 数组名 = new 数组元素类型[][]{数组1,数组2,数组3,...};
注意,二维数组中的元素类型是一维数组,把数组元素类型[]看成一个整体,表示数据类型。
public class ArrayInArrayDemo1 { public static void main(String[] args) { //定义三个一维数组 int[] arr1 = { 1, 2, 3 }; int[] arr2 = { 4, 5 }; int[] arr3 = { 6 }; //把三个一维数组存储到另一个数组中,那么该数组就是二维数组 int[][] arr = new int[][] { arr1, arr2, arr3 }; } }
定义和动态初始化二维数组的语法:
数组元素类型[][] 数组名 = new 数组元素类型[x][y];
x表示二维数组中有几个一维数组
y表示每一个一维数组中有几个元素。
int[][] arr = new int[3][5]; System.out.println(arr.length); //输出3
获取二维数组的元素
因为二维数组表示数组的中的数组,如果要获取数组的每一个元素值,则需要两个循环嵌套。
//二维数组 int[][] arr = new int[][] { { 1, 2, 3 }, { 4, 5 }, { 6 } };
使用for循环:
for (int index = 0; index < arr.length; index++) { //取出每一个一维数组 int[] arr2= arr[index]; //迭代一维数组 for (int j = 0; j < arr2.length; j++) { int ele = arr2[j]; System.out.println(ele); } System.out.println("-----"); }
使用for-each:
for (int[] arr2 : arr) { //arr2为每次遍历出来的一维数组 for (int ele : arr2) { //ele为从arr2一维数组中遍历出来的元素 System.out.println(ele); } System.out.println("-----"); }