
04-数组
回顾-03条件和循环
- 条件语句:if语句、switch语句
- 循环语句:for循环、while循环、do-while循环
- 嵌套的条件
- return、break、continue 关键字
- 逗号运算符
04-数组
回顾数据类型
- 数据类型:
- 八大基本数据类型
- 引用数据类型:数组、类类型(String、Scanner…)等等
- (了解)引用数据类型:引用类型指向一个对象,指向对象的变量是引用变量。
- Java是强类型语言。变量在声明时必须先定义数据类型。
//变量定义:type varName [=vaule];
int a, b=10;
// 思考: 定义变量存储100个int型数据?
数组的概念
- 什么是数组?
- 数组是有序数据的集合,且存储的元素具有相同的数据类型;
- 数组的组成:
- 数组名和下标
- 可以通过统一的数组名和下标来确定数组中的元素
- 数组的分类:
- 一维数组 + 多维数组(二维数组)
- Java中的一个数组是一个对象。(关于对象后续章节详讲)
(了解)引用数据类型:引用数据指向一个对象,而指向对象的变量就是引用变量。
一维数组
定义方式
- type arrayName [ ]; 或 type[ ] arrayName;
int intArr1[];
int[] intArr2; // 推荐使用:定义了一个int型数组intArr2
boolean[] shortArr;
String[] strArr;//类类型,声明了一个容纳引用数据类型String的数组
//未赋予初始值的数组是否有默认值?
system.out.println(intArr2); //在类体中定义,系统会自动赋予初始值,null
- 注意:
- type可以是Java中任意的合法的数据类型;
- [ ]指明这是数组,几个[ ]就表示几维数组。
- 数组为引用数据类型,所有的引用数据类型默认值为null。
- 思考:数组只定义,就可以引用或访问数组元素吗?
//定义了一个数组,可以引用或访问它的元素吗?
system.out.println(intArr2[0]); //通过数组名和下标,即arrName[下标],指定数组中的元素
- 所以,数组定义之后必须要初始化数组,才可以引用。
- Java中数组是对象,定义对象未初始化,即未给对象分配内存空间,所以无法对对象进行操作。
- 对数组进行初始化,就是为数组开辟连续的内存空间,并对数组元素赋值。--数组内存解析详讲
初始化
一维数组的初始化有两种方式:静态初始化+动态初始化
静态初始化:
- type[ ] arrayName = {元素1, 元素2,.....};
int[] array = {1,2,3,4}; //定义数组,给出初始化值,由系统决定长度
动态初始化--new关键字:
使用关键字new为数组分配连续的内存空间。
- type[ ] arrayName1 = new type[长度];
- type[ ] arrayName2 = new type[ ] {元素1,元素2,…};
int[] arr1 = new int[5]; // 数组arr1初始化,在内存中开辟了连续的5块空间
int[] arr2 = new int[]{11,22,33,44,55}; //数组arr2初始化,在内存开辟空间并依次存入5个数值。
一维数组的简单使用
- 获取元素:指定数组名和元素所在数组中的索引(即下标)
- 下标:只能是 int型,但是,根据数据类型转换,可以隐式转换到int型的数据类型也支持
- 长度:数组名.length
- 数组长度与下标关系
- 数组长度和数组最后的一个元素下标存在 length-1 的关系。
public static void main(String[] args) {
//静态初始化
int[] arr1 = {1,2,3,4,5};
//获取元素:通过数组名和下标,数组下标只能是整数型int型及以下类型
System.out.println("访问arr1 第一个元素:"+arr1[0]); // 1
//获取数组长度:数组名.length
System.out.println("获取arr1长度:"+ arr1.length); //5
//动态初始化--给固定长度
int[] arr2 = new int[5];
System.out.println("获取arr2长度:"+ arr2.length); //5
//初始化时,我们未赋值的情况下,系统会帮忙给出相应的数据类型的默认值
System.out.println("访问arr2 第一个元素:"+arr2[0]); // 0
//动态初始化--未给固定长度
int[] arr3 = new int[]{1,2,3,4};
//初始化时,程序员给元素赋予初始值
System.out.println("arr3 第四个元素值:" + arr3[3]); //4
System.out.println("获取arr3长度:"+ arr3.length); //4
//开辟内存空间 和 给定初始值`不能同时使用`
// int[] arr3 = new int[4]{1,2,3,4}; //编译报错
动态初始化需要注意:
- 定义数组,指定开辟空间长度,由系统赋予对应的数据类型的默认值;--数组内存解析
- 定义数组,未指定开辟空间长度,则必须赋予初始值。 -- 由程序员赋予数组元素初始值
- 开辟内存空间 和 给定初始值不能同时使用。
动态初始化元素初始值问题
- 一维数组动态初始化有两种方式:
- 如果只new(即只分配了内存空间)没有赋值,系统会为数组中的每个元素赋予对应数据类型的默认初始值
整型数组所有元素为0;
浮点型数组所有元素为0.0;
布尔型数组所有元素为false;
字符型默认初始值为空字符,\u0000,' '
- 类类型数组所有元素为null;
- new的同时给定元素初始值,则系统不再为元素赋初始值。
案例2:动态初始化只new未定义元素初始值,求数组中的每个元素默认值
//数组初始化未赋初始值,此时数组元素的默认值
public static void main(String[] args) {
int[] arrInt =new int[3];
System.out.println("int型数组只new未给定初始值,此时元素初始值为:"+arrInt[0]);
double[] arrDouble =new double[3];
System.out.println("double型数组只new未给定初始值,此时元素初始值为:"+arrDouble[0]);
boolean[] arrBoolean = new boolean[3];
System.out.println("boolean型数组只new未给定初始值,此时元素初始值为:"+arrBoolean[0]);
char[] arrChar =new char[3];
System.out.println("char型数组只new未给定初始值,此时元素初始值为:"+arrChar[0]+"。");
String[] arrString =new String[3];
System.out.println("String型数组只new未给定初始值,此时元素初始值为:"+arrString[0]+"。");
System.out.println("String属于类类型,可以代表所有引用数据类型,引用数据类型默认值都为 null");
}
案例3:数组常见异常现象
//空指针异常:数组未初始化,数组是对象,对象初始化在堆中开辟内存空间后,才能对对象内容进行访问和操作。
//java.lang.NullPointerException
int[] arr1 = null;
System.out.println(arr1[0]); //未初始化,无法对数组元素操作
//数组下标越界
//java.lang.ArrayIndexOutOfBoundsException: 4
int[] arr2 = {1,2,3,4};
System.out.println("访问arr2中第五个元素:"+arr2[4]);
案例4:遍历数组中的元素
- 定义数组,元素的值是随机的(小于100之内,不能是0)。求数组中最大元素的值以及所在的下标。
- 根据数组长度与下标关系,对数组中的元素进行遍历
- 使用for循环
public static void main(String[] args) {
int[] ary1 = {22, 33, 12, 93, 55, 67, 85};
int max = 0,index=0;
for (int i =0; i<ary1.length; i++){ int num = ary1[i]; if(max < num) { max =num; index =i; } } System.out.println("数组中最大值为:max="+max+",数组下标为:"+index); } ``` 案例5:使用增强for循环遍历数组元素 - JDK1.5之后,增强循环 foreach循环,foreach其实是for循环的一个特殊简化版。 ```java //增强foreach遍历输出 int[] ary2 = {1, 2, 3, 4, 5, 22, 33, 12, 93, 55, 67, 85}; int i =0; for (int num : ary2){ System.out.println("arr2["+i+"]="+num); i++; } ``` 案例6:冒泡排序<br/>冒泡排序的计算原理:
1. 比较相邻的元素。按照小的在前,大的在后的顺序排列。
2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3. 针对所有的元素重复以上的步骤,除了最后一个。
4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

```java
public static void test() {
int [] array= {6,2,3,0,67,43,65,8,87,89,76,23,54,542,45};
//获取需要进行比较的趟数,由序列元素长度决定
int n = array.length;
int tmp = 0; // 临时变量
//遍历序列,通过外部循环控制所有趟数,而内部循环实现每一轮的冒泡处理
for (int i = 0; i < n; i++) {
for (int j = 0; j < n-i-1; j++) {
//每趟中进行n-i次比较,并且最后一个元素不需要进行比较
if(array[j] > array[j+1]) {
tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
}
}
}
//foreach
System.out.println("经过冒泡排序后:");
for(int num:array) {
System.out.print(num+" ");
}
}
数组内存解析
数据类型内存解析
- 八大基本数据类型
- 直接在栈内存中,开辟一个空间,由变量命名,存储着常量。
- 要对该常量数据进行操作和访问,直接访问变量名。
- 栈中的变量默认值,为该数据类型的默认值。-- 基本数据类型相应默认值,引用数据类型为null
- 引用数据类型(数组)
- 引用数据指向一个数组对象,而指向数组对象的变量就是引用变量。
- 当定义了一个引用类型的数组时,系统在栈内存当中开辟一个由数组名命名的内存空间,该内存空间(数组名)中存放的是堆内存中的引用对象的 引用(即是内存地址)。而在此时如果不进行初始化直接使用,也就是引用对象的引用并没有指向任何目标对象(此处指数组对象),就直接访问,就当然会报空指针异常的错误。
数组内存解析
- 疑问:数组要怎么存呢?
- 画图举例子:盖楼,得找政府批地,盖在哪里都有个具体的地址,在计算机内存中也有具体的地址。如果要找到每个房间怎么办,其实它们都有个编号,就像楼层一样。如果要去访问它们只要通过具体的地址加上编号就能找到它,比如创业大厦911房间
//左边通过声明int型数组,在栈中开辟一个命名为ary的空间
//右边通过new方式在堆中开辟一个内存存放int型数据。
int[] ary =new int[5];
system.out.println(ary); //打印的是ary1的堆中内存地址
ary = null //则是直接把ary1的堆中内存地址给清空,此时栈中arr=null,未指向堆中引用对象

public static void main(String[] args) {
// 数组的内部分析
int[] arr1 = new int[2];// {0,0}
int[] arr2 = new int[2];// {0,0}
System.out.println("arr1=" + arr1);// [I@7852e922
System.out.println("arr2=" + arr2);// [I@4e25154f
//== 是比较地址
System.out.println(arr1 == arr2);//false
arr1[0]=99;
System.out.println("arr1[0]="+arr1[0]);//99
System.out.println("arr2[0]="+arr2[0]);//0
arr2=arr1;
System.out.println("arr2[0]="+arr2[0]);//??
}
多维数组(二维数组)
在任何语言中,多维数组都被看作数组的数组。比如二维数组是一个特殊的一维数组,其每一个元素又是一个一维数组。
定义方式(3种)
- type arrayName[ ] [ ] ;
- type[ ] [ ] arrayName;
- type[ ] arrayName[ ] ;
与一维数组一样,只对数组声明,并未对二维数组元素分配内存空间,同样需要对二维数组进行初始化,来分配内存,然后才可以访问每个元素。
初始化
静态初始化
- 在定义数组的同时为数组分配空间
- 语法:type[ ][ ] arrayName = {{...},{...},{...}}
- 不必指定数组中每一维的大小,系统会根据初始化时,给出的初始值的个数计算出数组中每一维的大小
int[][] arrInt = {{1,2},{3,4,5},{6,7,8}};
//二维数组arrInt中有3个元素,每个元素为一维数组
//第一个元素的一维数组长度为2
//第二个元素的一维数组长度为3
//第三个元素的一维数组长度为3
System.out.println(arrInt[2][0]);//??
动态初始化(3种)
通过关键字new为数组分配连续的内存空间。
- 直接为每一维分配空间
- 语法:type[ ][ ] arrayName = new type[n][m]; //n和m为int型及int型以下类型
- 只创建了二维数组对象(每一个一维数组是空的)
- 语法:type[ ][ ] arrayName = new type[n][ ];
- 带指定值的动态初始化
- 语法:type[ ][ ] arrayName = new type[ ][ ] {{10,20},{30,40,50}};
- 相当于静态初始化的复杂写法,一般不推荐。
//为每一维都分配了空间,系统自动给定的默认值为相应数据类型的默认值
int[][] arr=new int[2][3];//{{0,0,0},{0,0,0}}
//只创建了二维数组对象,系统自动给定的默认值{null,null},为什么?
int[][] arr = new int[2][];//{null,null}
//因为数组属于引用数据类型,是对象,默认值为null
//为二维数组中的一维数组初始化:
arr[0] = new int[2]; //arr[0] 相当于 int[] arr0 = new int[2];//{0,0}
arr[1] = new int[]{11,22,33};//arr[1] 相当于 int[] arr1 = new int[]{11,22,33};
简单使用
- 获取元素:数组名和元素所在具体维数中的索引(即下标)
- arrayName[n][m]; //对应二维表格 第n列第m行
- 下标:只能是 int型,但是,根据数据类型转换,可以隐式转换到int型的数据类型也支持
- 长度(2种):二维数组是特殊的一维数组,里面每一个元素都是一维数组;
- 获取二维数组的元素长度(个数):
- 数组名.length;
- 获取第一个一维数组的元素长度:
- 数组名[0].length; 依次类推;
- 获取二维数组的元素长度(个数):
- 数组长度与下标关系
- 数组长度和数组最后的一个元素下标存在 length-1 的关系
public static void main(String[] args) {
// 二维数组:存放有序数据集合,二维数组中的每一个元素都是一维数组
// 定义方式:
// 语法:
// type [][] arrayName
// type arrayName [][]
// type []arrayName[]
// 二维数组的初始化方式:
// 1.静态初始化
// 语法:type [][] arrayName = {{...},{...},{...}}
int[][] intArr1 = { { 1, 2 }, { 3, 4, 5 }, { 6, 7 } };
int size = intArr1.length;
int size1 = intArr1[0].length;
System.out.println("获取二维数组intArr1长度:"+size);// 3
System.out.println("获取第一个元素一维数组intArr1[0]长度:"+size1);// 2
System.out.println("intArr1=" + intArr1);// [[I@7852e922
System.out.println("intArr1[0]=" + intArr1[0]);// 二维数组中一维数组的地址[I@4e25154f
// 2.动态初始化
// 1) type [][] arrayName = new type[n][m];
// n表示:一维数组个数; m表示每一维数组的长度
int[][] intArr2 = new int[2][3];// 表示有两个一维数组且长度都为3的二维数组,系统给定相应默认值 {{0,0,0},{0,0,0}}
System.out.println(intArr2[0]);// [I@3a25a54f
System.out.println(intArr2[0][0]);// 系统给定相对应的默认值 0
intArr2[0][0]=15;
System.out.println(intArr2[0][0]);//15
// 2) type [][] arrayName = new type[n][];
int[][] intArr3 = new int[2][];
System.out.println(intArr3[0]);// null
System.out.println(intArr3[1][0]);// 空指针异常,一维数组未初始化
//为二维数组中元素,即一维数组初始化
intArr3[0] = new int[3];
intArr3[1] = new int[]{11,22,33};
// intArr3[1]={1,2,3};//不能采用一维数组静态初始化的方式
// 3) type [][] arrayName = new type[][]{{...},{...}}; //静态初始化复杂写法
int[][] intArr4 = new int[][] { { 1, 2, 3 }, { 2, 3 } };
System.out.println("相当于二维表格,第1列第2行元素:"+intArr3[0][1]);
}
public static void main(String[] args) {
int [][] arr1= {{1},{1,1},{1,2,1},{1,3,3,1},{1,4,6,4,1},{1,5,10,10,5,1}};
for(int i=0;i<arr1.length;i++) {
for(int j=0;j<arr1[i].length;j++) {
System.out.print(arr1[i][j]+" ");
}
System.out.println();
}
//foreach
for(int num[]:arr1) {
for(int sc:num) {
System.out.print(sc+" ");
}
System.out.println();
}
}
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Eternal Night
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果