1.数组
-
定义:
是多个相同类型得数据按一定顺序排列得集合,并使用一个名字命名,并通过编号得方式对这些数据进行统一管理
-
常见概念:
- 数组名
- 角标、下标(或索引)
- 元素
- 数组得长度(元素得个数)
-
数组得特点:
数组是有序排列得
-
说明:
1.数组本身是引用数据类型,而数组中得元素可以是任意数据类型,包括基本数据类型和引用数据类型
2.创建数组对象会在内存中开辟一整块连续得空间,而数组中引用得是这块连续空间得首地址
3.数组得长度一旦确定。就不能修改
4.可以直接通过下标(或索引)得方式调用指定位置得元素,速度很快
-
分类:
- 按照维度:一维数组、二维数组、三维数组
- 按照元素得数据类型分:基本数据类型元素得数组、引用数据类型元素得数组(即对象数组)
- 按照维度:一维数组、二维数组、三维数组
1.1 一维数组
1.1.1 使用
- 一维数组得声明和初始化
- 如何调用数组指定位置得元素
- 如何获取数组得元素
- 如何遍历数组
- 数组元素得默认初始化值
- 数组得内存解析
一维数组使用1.2.3.4得测试用例:
public class Array_Test {
public static void main(String[] args) {
int num; //普通整型变量得声明
num = 10; //初始化
int num1 = 10; //声明 + 初始化
//1.一维数组得声明和初始化
//声明方式1,创建数组对象时指定元素和长度得数组声明
//数组得初始化和数组元素得赋值操作同时进行
int[] arr; //声明
//1.1 静态初始化
arr = new int[] {1,2,3,4}; //初始化,要使用引用数据类型必须创建对象来使用其中得属性和方法
//声明方式2,创建数组对象时指定长度(最多可以存储元素得个数),但是不指定其中得具体元素得数组声明
//1.2 动态初始化
//数组得初始化和数组元素得赋值操作分开进行
String[] names = new String[5]; //声明 + 初始化,指定数组的长度和数据类型,但是具体元素暂不进行赋值
//总结:数组一旦初始化完成,那么长度就是可以确定得了
//2.调用数组指定位置得元素:通过角标方式来进行查找
//Java中数组得角标(索引)是从0开始得,那么数组最大调用角标就为:数组得长度 - 1
names[0] = "张三"; //数组中得第一个元素的角标为0
names[1] = "李四";
names[2] = "王五";
names[3] = "赵六";
names[4] = "孙七"; //数组中得最后一个元素得角标为:数组长度 - 1 = 4
//names[5] = "钱八"; //出现运行时错误,错误信息为 java.lang.ArrayIndexOutOfBoundsException: 5(数组角标越界)
//3.如何获取数组得长度
//属性:length
System.out.println(names.length); //5
//4.如何去遍历数组元素
for(int i = 0;i < names.length;i++) {
System.out.print(names[i] + " ");
}
//输出:张三 李四 王五 赵六 孙七
}
}
一维数组使用5得测试用例:
/*5.数组元素得默认初始化值:
* >数组元素是整型:0
* >数组元素是浮点型:0.0
* >数组元素是char字符类型:0或字符 不是'0'字符,而是ASCII码值为0处得字符
* >数组元素是布尔类型:fasle
*
* >数组元素是引用数据类型得时候:null
*
*6.数组得内存解析:
* */
public class ArrayTest1 {
//5.数组元素得默认初始化值
public static void main(String[] args) {
int[] arr = new int[5];
for(int i = 0;i < arr.length;i++) {
System.out.print(arr[i] + " "); //0 0 0 0 0
}
System.out.println();
char[] arr1 = new char[5];
for(int i = 0;i < arr1.length;i++) {
System.out.print(arr1[i] + "---"); //0 0 0 0 0
}
System.out.println();
String[] arr2 = new String[6];
System.out.println(arr2[0]);
}
}
数组元素内存解析:
具体执行代码:
(1)int[] arr = new int[]{1,2,3};
(2)String[] arr1 = new String[6];
(3)arr1[1] = “张三”;
(4)arr1[2] = “李四”;
(5)arr1 = new String[3];
注意:只要见到new关键字 + 类名就意味着在堆内存中创建对象
一维数组得内存解析:
一维数组得课后练习测试用例:
import java.util.Scanner;
/*从键盘读入学生成绩,找出最高分,并输出学生成绩等级
* >成绩 = 最高分 - 10 等级为'A'
* >成绩 = 最高分 - 20 等级为'B'
* >成绩 = 最高分 - 30 等级为'C'
* >其余 等级为'D'
*
* */
public class ArrayDemo1 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("请输入学生得个数: ");
//1.获取学生个数
int number = scan.nextInt();
System.out.println("请输入" + number +"个成绩");
//2.定义一维数组型变量来存储学生成绩
int[] score = new int[number];
//3.从控制台获取学生成绩
int i = 0;
while(i < score.length) {
score[i] = scan.nextInt();;
i++;
}
//4.获取最高分
int maxScore = 0;
for(int j = 0;j < score.length;j++) {
if(maxScore <= score[j]) {
maxScore = score[j];
}
}
System.out.println("最高分是" + maxScore);
//5.获取各个学生得等级
String level = "";
for(int k = 0;k < score.length;k++) {
if(maxScore - score[k] <= 10) {
level = "A";
}else if(maxScore - score[k] <= 20) {
level = "B";
}else if(maxScore - score[k] <= 30) {
level = "C";
}else {
level = "D";
}
System.out.println("sudent " + k + " score is " + score[k] + " grade is " + level);
}
}
}
1.2 多维数组
1.2.1 理解:
对于二维数组得理解,可以看成是是一个一维数组array又作为另一个数组array1得元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组(只不过一维数组里面得元素还是一个一维数组,所以称之为二维数组)
1.2.2 使用:
- 二维数组得声明和初始化
- 如何调用数组指定位置得元素
- 如何获取数组得元素
- 如何遍历数组
- 数组元素得默认初始化值
- 数组得内存解析
二维数组使用1,2,3,4的测试用例:
public class ManyArray_Test {
public static void main(String[] args) {
//1.二维数组得声明和初始化(一个[]代表数组中得一个维度)
int[] arr = new int[] {1,2,3}; //一位数组得静态初始化
int[][] arr1 = new int[][] {{1,2,3},{5},{6,7}}; //二维数组得静态初始化
//{1,2,3}又是一个数组,代表外层数组中得第一个元素
//{5}又是一个数组,代表外层数组中得第二个元素
//{6,7}又是一个数组,代表外层数组中得第三个元素
//动态初始化1
String[][] arr2 = new String[3][2];
//第一维为3,指定外层数组中有三个元素(外层数组得每一个元素为一维内层数组)
//第二维为2,指明内层数组中有两个元素(内层数组作为外层数组中得元素而存在)
//动态初始化2
String[][] arr3 = new String[3][];
//第一维为3,指定外层数组中有三个元素(外层数组得每一个元素为一维内层数组)
//第二维空间可以在创建二维数组对象时暂不指定具体长度,等到有具体需求得时候可在定义
//注意:二维数组得第一维维度必须指定长度,否则编译不通过,第二维维度可指定也可不指定
/*错误情况:
* int[][] arr = new int[][4];
* //错误,在定义二维数组得时候,第一维长度必须指定
*
* int[4][3] arr = new int[][3];
* //错误,前面定义变量[][]只是进行声明得作用,里面不能对维度进行初始化
*
* int[][] arr = new int[4][3]{{1,2,3},{5},{6,7}};
* 错误,静态初始化和动态初始化混杂,啥也不是,定义是要么不定义具体维度,给出具体数组元素。要么只定义具体维度,不给出数组中得具体元素
* */
//其他正确情况:
int arr4[][] = new int[4][3];
//[][]可以放在变量名之后声明
int []arr5[] = new int[4][3];
//[][]可以分别一前一后定义在变量名前后位置,但是这样做不符合通常的定义规范,不建议使用
int[][] arr6 = {{1,2,3},{5},{6,7}};
//java虚拟机进行自动类型推断,根据前驱定义,识别方面定义得数据与前驱一致
//声明 + 初始化分开来写,那么就不能进行自动类型推断了,会报错
//2.如何调用数组中得指定位置上得元素
System.out.println(arr1[0][1]); //2
//调用二维数组arr1得外层数组元素位置为0,内层数组元素位置为1上的元素
System.out.println(arr2[1][1]); //null默认初始化值
//调用索引位置为1,1得元素,实际位置是第二行第二列得元素
arr3[1] = new String[4];
//为arr3数组中得索引为1,实际位置为2得元素开辟第二维空间,并指定长度
System.out.println(arr3[1][1]); //运行出错,空指针异常
//想调用索引位置为1,1得元素,但是第二维中还未开辟空间,所以指向了一个寂寞,指向为空
//如果想进行调用,可以在调用此位置元素之前,指定第二维,为第二维开辟内存空间
//3.获取数组的长度
System.out.println(arr1.length); //3
//获取外层数组可存储元素(这里的每一个元素又指内层的一个一维数组)个数(长度)
System.out.println(arr1[0].length); //3
//获取外层数组元素指定索引处为0,内层数组长度(可存储数据的容量大小)
//4.如何遍历二维数组:使用双层for循环
for(int i = 0;i < arr1.length;i++) { //外层循环控制外层数组索引
for(int j = 0;j < arr1[i].length;j++) { //内层循环控制内层数组索引
System.out.print(arr1[i][j] + " ");
//第一次内层循环执行完输出:1 2 3
//第二次内层循环执行完输出:5
//第三次内层循环执行完输出:6 7
}
System.out.println();
}
}
}
二维数组使用5的测试用例:
/*二维数组的使用:
* 规定:外层数组分为外层数组元素和内层数组元素
* int[][] arr = new int[4][3];
* 外层元素:arr[0]、arr[1]、...等
* 内层元素:arr[0][0]、arr[1][1]、...等
*
* 5.数组元素的默认初始化
* 针对于int[][] arr = new int[4][3];的初始化方式
* 外层元素:地址值
* 内层元素:根据定义二维数组的数组的数据类型来确定,两者保持一致(与一维数组默认初始化情况相同)
*
* 针对于int[][] arr = new int[4][];的初始化方式
外层元素:null(每个元素是一个数组,数组本身就是引用数据类型,那么默认初始话值为null)
内层元素:不能调用,因为第一维为null,那么它指向第二维(还未开辟内存空间),肯定就指向了寂寞,运行时出错,报出空指针异常的错误
*
* 6.数组的内存解析
*
*
*
* */
public class ManyArray1_Test {
public static void main(String[] args) {
//5.默认初始化
int[][] arr = new int[4][3];
System.out.println(arr[0]); //[I@7852e922
//最外层存放的是元素(内层数组)的首地址值,指向的是堆内存中内层数组的首地址值
//地址值解析:'['代表存放的元素为一维数组类型,'I'代表的是元素的数据类型为int整型数据,'@7852e922'代表随机地址值
System.out.println(arr[0][0]); //0
//已经到了最内层了,默认初始化的值与定义的二维数组时的数据类型相一致
System.out.println(arr); //[[I@4e25154f
//6.内存解析
}
}
二维数组元素内存解析:
具体执行代码:
(1)int[] [] arr1 = new int [4] [ ];
(2)arr1[1] = new int[]{1,2,3};
(3)arr1[2] = new int[4];
(4)arr1[2] [1] = 30;
二维数组执行语句解析内存图:
注意例题:
int[]x,y[];在给x,y变量赋值以后,以下选项允许通过编译的是:
a) x[0] = y; //错误
b) y[0] = x; //正确
c) y[0] [0] = x; //错误
d) x[0] [0] = y; //错误
e) y[0] [0] = x[0]; //正确
f) x = y; //错误
解析:
连续赋值含义理解清楚,例如:int x,y = 10;将x和y变量都定义为int整型的数据类型,并且都赋值为10,那么int[] x,y;就是将x和y都定义为int整型的一维型数组变量,
那么int[] x,y[];就是将前者定义为整型的一维型数组变量x,因为在定义y的时候,y自身也带了一个维度,再加上前面整体定义的一个维度,那么y就是整型的二维数组变量。然后接下来就分别理清楚各层其中存放的元素类型,然后把握赋值语句的要素,小到大,自动类型提升,大到小,强制类型转换,基本数据类型之间可以转换,基本数据类型和引用数据类型之间不能相互赋值,但是能相互转换。