Java05数组
一、数组
数组指的是一种容器,可以用来存储同种数据类型的多个值。
1、数组的静态初始化
初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程
1.1 数组定义格式
//格式一
数据类型[] 数组名
//格式二(C中用的多,Java用的少)
数据类型 数组名[]
注意:定义数组只是定义了数组类型的变量而已,内存中并没有正真将数组容器创建出来,还需要初始化内存才会为数组容器开辟空间。
1.2 静态初始化
-
完整格式
数据类型[] 数组名 = new 数据类型[] {元素1,元素2,元素3,...};
int[] array = new int[]{11,22,33}; double[] array2 = new double[]{11.1,22.2,33.3};
-
简化格式(常用)
简化格式只是简化了代码书写,运行还是会按照完整格式运行
数据类型[] 数组名 = {元素1,元素2,元素3,...};
int[] array = {11,22,33}; double[] array2 = {11.1,22.2,33.3};
1.3 注意事项
public class ArrayDemo1 { public static void main(String[] args) { int[] arr1 = new int[]{11,22,33}; double arr2[] = {11.1,22.2,33.3}; System.out.println(arr1); System.out.println(arr2); } }
打印数组名,会看到数组在内存中的十六进制地址值
2、数组元素访问
格式:数组名[索引]
索引:是数组容器中空间的编号,编号从0开始,逐个+1增长;
public class ArrayDemo1 { public static void main(String[] args) { //char类型的a取值范围小,int类型取值范围大,可以这样存,但没必要 int[] arr1 = new int[]{11,22,33,'a'}; int num = arr[0]; System.out.println(num) } } //运行结果为11
3、数组遍历操作
3.1 遍历
将数组中所有的内容取出来,取出来之后可以(打印、求和、判断...)
public class ArrayDemo3 { public static void main(String[] args) { int[] arr = {11,22,33,44,55}; //arr.length动态获取数组长度 for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
快捷键:数组名.fori 回车
3.2 综合案例(求和最大最小值)
public class ArrayTest2 {
public static void main(String[] args) {
int[] arr = {33,11,55,44,22};
int max = arr[0]; //定义记录最大值的变量,初始值为数组的第一个元素
int min = arr[0]; //定义记录最小值的变量,初始值也为数组第一个元素
int sum = 0; //定义求和变量
for (int i = 0; i < arr.length; i++) {
//数组元素大于最大值
if(arr[i]>max){
//更新最大值
max=arr[i];
}
//数组元素小于最小值
if(min>arr[i]){
//更新最小值
min = arr[i];
}
//累加数组变量
sum+=arr[i];
}
//循环结束,打印结果
System.out.println("最大值为:"+max);
System.out.println("最小值为:"+min);
System.out.println("数组元素和为:"+sum);
}
}
4、数组动态初始化
初始化时只指定数组长度,由系统为数组分配初始值
4.1 格式
数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr = new int[3];
4.2 默认初始值
数据类型 | 默认初始值 |
---|---|
整数(基本类型) | 0 |
小数(基本类型) | 0.0 |
字符(基本类型) | '\u0000' 常见体现为空白字符 |
布尔(基本类型) | false |
类、接口、数组(引用类型) | null |
4.3 ⭐两种初始化的区别
动态初始化 | 静态初始化 |
---|---|
手动指定数组长度 | 手动指定数组元素 |
系统给出默认初始化值 | 系统会根据元素个数计算数组长度 |
Q如何选择?(使用场景)
-
需求中已经明确给出要操作的数据时,直接静态初始化
-
只明确元素个数,不明确具体数值时,使用动态初始化
5、数组内存图
5.1 Java内存分配介绍
-
栈
方法运行时所进入的内存,方法运行结束要弹栈
-
堆
new出来的东西会在这块内存中开辟空间并产生地址值
-
方法区
字节码文件加载时进入的该内存
-
本地方法栈
属于栈内存的一部分,负责加载一些特殊的方法(native修饰的方法,底层是调用C++代码,我们是无法看到方法内部的实现逻辑)
-
寄存器
CPU使用
5.2 两个数组指向相同 内存图
5.3 相关面试题
-
总结
方法的参数传递: 1、基本数据类型:数据值 2、引用数据类型:地址值 Q:Java是值传递,还是地址传递? A:分情况,基本数据类型传递数据值,引用数据类型传递地址值 詹姆斯高斯林:值传递,地址值也是值
6、数组常见问题
6.1 索引越界异常
ArrayIndexOutOfBoundsException:当访问了数组中不存在的索引,就会引发索引越界异常
public class ArrayIndexOutOfBoundsExceptionDemo { public static void main(String[] args) { int[] arr = {11,22,33}; System.out.println(arr[3]); } }
6.2 空指针异常
当引用数据类型变量被赋值为null之后,地址的指向被切断,还继续访问堆内存数据,就会引发空指针异常
public class NullPointerException { public static void main(String[] args) { int[] arr = {11,22,33}; arr= null; System.out.println(arr[0]); } }
二、二维数组
一种用于存储一维数组的容器
使用思路:要操作的多组数据,又属于同一组数据,就使用二维数组进行维护
1、静态初始化
-
完整格式
数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2},{元素1,元素2}};int[][] arr = new int[][]{{11,22},{33,44}};
-
简化格式
数据类型[][] 数组名 = {{元素1,元素2},{元素1,元素2}};int[][] arr = {{11,22},{33,44}};
2、元素访问
格式:数组名[索引] [索引];
public class ArrayDemo1 { /* 元素访问:数组名[m][n] m: 访问哪个一维数组 n: 访问一维数组的哪个元素 */ public static void main(String[] args) { int[][] arr = { {11,22,33}, {44,55,66} }; //打印二维数组名,会出现它所记录的一维数组的地址 System.out.println(arr); //访问元素33 System.out.println(arr[0][2]); } }
3、二维数组遍历
思路:使用嵌套循环,先拿到二维数组里每个一维数组的地址,再通过遍历每个一维数组访问其中的元素,嵌套起来,就可以遍历到整个二维数的所有元素了
public class ArrayDemo2 { /* 二维数组遍历 需求: 求二维数组中偶数元素的和 */ public static void main(String[] args) { int[][] arr={ {11,22,33}, {44,55,66} }; //定义求和变量 int sum = 0; //遍历二维数组,获取每一个一维数组 for (int i = 0; i < arr.length; i++) { //arr[i]代表每一个数组 //继续遍历一维数组,取出元素 for (int j = 0; j < arr[i].length; j++) { if(arr[i][j]%2 == 0){ //累加求和 sum+=arr[i][j]; } } } System.out.println(sum); } }
4、动态初始化
-
格式
数据类型[][] 数组名 = new 数据类型[m][n]; m表示这个二维数组,可以存放多少个一维数组 n表示每一个一维数组,可以存放多少个元素int[][] arr = new int[2][3];
-
默认初始值
二维数组存放的是一维数组的地址值,而一维数组是引用数据类型,所以默认值为null
数据类型 默认初试值 一维数组 null