前言
在之前我们可以通过一个变量表示一个学生的年龄,如果现在需要表示全班 100 个人的年龄岂不是需 要定义 100 个变量来分别表示。这样的操作变量的命名容易冲突,并且也会导致代码量大,可读性差等问题。那么怎么解决这种问题呢?Java 就提供了数组解决这种问题。
1、数组概念
概念:计算机在内存区域分配的一段连续的区域,用来存储同种类型的数据。
简单的理解,数组就是一堆盒子,同一时间,可以保存多个相同数据类型的数据。

- 数组名 :数组的名字。
- 数组元素:就是存放在数组里面的数据。
- 数组索引:就是数组里面连续存储空间的编号,从0开始。
- length :数组的属性长度,数组名.length拿到数组的长度。
数组作用:可以解决同时保存多个数据的问题。
2、数组声明
回忆定义变量的语法: 数据类型 变量; 如 int age;
数组的声明语法:
数据类型[] 数组名; 【目前只是单纯声明,还不能使用】
如:
int[] ages; // 表示声明一个int类型数组ages,这个数组只能装int类型元素
String[] names; // 表示声明一个String类型数组names,这个数组只能装String类型元素另一种方式:int ages[];【不推荐】。
3、数组赋值
数组在定义后,必须初始化【赋值】才能使用。所谓初始化,就是在堆内存中给数组分配存储空间,并为每一个元素赋上初始值,有两种方式:
3.1、动态创建
语法:数据类型[] 数组名 = new 数据类型[长度];// 长度不能为负数,且是int类型 最大就是int最大值。
// 数组声明: 动态创建,语法 :数据类型[] 数组名 = new 数据类型[长度];
//长度不能为负数,且是int类型 最大就是int最大值
int[] arr = new int[3]; // 动态创建了一个int类型的数组arr,长度33.2、静态创建
语法:数据类型[] 数组名 = {值1, 值2, 值3.....};// 最常用
语法:数据类型[] 数组名 = new 数据类型[]{值1,值2,值3.....};// 不常用。了解
// 数组声明:静态创建,语法 :数据类型[] 数组名 = {元素1, 元素2, 元素3....};
int[] arr2 = {6, 9, 69}; // 静态创建了一个int类型的数组arr,赋值元素 :6, 9, 69怎么选择用动态创建还是静态创建?
根据实际情况确定,知道具体的数据,用静态创建,不知道用动态创建。
3.3、数组赋值
语法:数组名[下标] = 值;
// 2 数组赋值:语法,数组名[下标] = 值;
arr[0] = 1; // 给数组arr第1个元素赋值1
arr[1] = 2; // 给数组arr第2个元素赋值2
arr[2] = 3; // 给数组arr第3个元素赋值34、数组取值
语法:数组名[下标];
取值后,主要用于:
- 直接打印输出
- 赋值给另外一个变量
- 直接计算
- 作为方法参数使用
// 数组取值:语法,数组名[下标]; 直接打印元素即可 System.out.println("第1个元素 : " + arr[0]); // 直接打印第1个元素 System.out.println("第2个元素 : " + arr[1]); // 直接打印第2个元素 System.out.println("第3个元素 : " + arr[2]); // 直接打印第3个元素
5、数组遍历
遍历:就是将数组中每一个元素取出来。
5.1、for + index【普通for循环】
根据上面取值的代码,可以发现一个规律,下标都是从0开始,到length-1结束。因此我们通过循环可以得到下标,而得到下标后,进而可以通过下标获取对应元素:
数组遍历【将所有元素取出来就是遍历】
// 先打印数组arr所有下标
for (int i = 0; i < arr.length; i++) { // i表示下标,循环次数就是到 最后一个下标arr.length - 1
// 打印下标:i
System.out.println("下标:" + i);
// 打印元素:arr[i]【通过下标获取对应元素】
System.out.println("元素==== :" + arr[i]);
}5.2、增强for循环
语法:
for(元素类型 e : 数组/集合){
e是变量,随便命名。就是每次获取到的元素
}
/*
* 数组遍历第二种方式:增强for循环 foreach
*
* 方式2: 简化遍历数组的过程
* 2. 增强for循环: foreach
语法:
for(元素数据类型 变量名 : 数组名){
变量名 //就是每一次获取到的元素
}
*/
for (int e : arr) { // arr是数组名, int 是元素类型 e变量是每一个元素
System.out.println("元素 :" + e);
}5.3、数组的内存图
/**
* 数组内存分析图【理解】
* 基本类型具体的值在栈帧中
* 引用类型具体的值在堆中
*/
public static void main(String[] args) {
int[] arr2 = {1, 2, 5};
int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr);
arr[0] = 1;
arr[1] = 9;
arr[2] = 6;
// arr[3] = 5; // ArrayIndexOutOfBoundsException 数组下标越界异常。证明下标超过了数组有效范围
int a = 1;
int b = 1;
a = 2;
}5.4、分析图:

6、数组注意事项
1、数组的下标范围是[0,arr.length-1],使用数组的时候,超过下标范围会报错
ArrayIndexOutOfBoundsException 数组下标越界异常。
例如:数组长度是3个,但是现在操作第4个元素arr[3]就会报这个错误。
2、数组动态创建可以分为两步:
2.1、int[] arr; //只是声明一个int类型的数组,还没有创建(即,还没有分配内存空间)
2.2、arr = new int[长度]; //分配内存空间,动态创建数组
3、数组静态创建可以分为两步:
3.1、int[] arr; //只是声明一个int类型的数组,还没有创建(即,还没有分配内存空间)
3.2、arr = new int[]{1,2,43}; // 分配内存空间,动态创建数组
不能直接这样写:arr = {1,2,43}; // 语法错误
4、数组一旦创建,长度就固定不变了。
如果长度不够或者长度多了,就需要创建新数组,将原来数组中元素复制到新数组中。int[] arr = {1,2,43};
arr = new int[]{1,43}; //开辟新的内存区域,重新创建新的数组扩容、缩容
5、数组是引用数据类型,直接打印数组名是打印的地址
6、动态创建,没有给数组元素赋值,则系统会分配默认值
(byte/short/int/long)整数类型默认值:0
(float、double)小数类型默认值:0.0
boolean类型:false
char类型默认值:空字符
7、空指针异常:NullPointerException,操作了一个尚未初始化或者没有分配内存空间的数组,即,没有只是声明,但是没有创建的数组。
8、数组声明可以这样,但是不建议
int arr[] = new int[2];// []在数组名后,不建议
6.1、部分测试代码:
public class _06Array {
/** static修饰int[]类型成员变量newArr,声明不赋值 */
static int[] newArr;
public static void main(String[] args) {
// 静态创建分2步
int[] arr2;
// 创建
arr2 = new int[]{1, 2, 5};
// 动态创建分2步
int[] arr;
arr = new int[2];
// 使用成员变量newArr
System.out.println(newArr); // null
// 使用成员变量newArr.length
System.out.println(newArr.length); // NullPointerException空指针异常
int arr3[] = new int[2]; // 不建议
}
}7、数组联系题【建议初学者学习】
public static void main(String[] args) {
// 需求 1:找出数组nums中元素 22 第一次出现的索引位置
int[] nums = {11, 22, 33, 44, 22, 55};
/*
* 分析:普通for循环【因为用下标】,遍历数组nums,将每一个元素跟22比较,如果相等,就打印下标,结束break循环
*/
// 普通for循环【因为用下标】,遍历数组nums
for (int i = 0; i < nums.length; i++) {
// if判断,将每一个元素nums[i]跟22比较,如果相等
if (nums[i] == 22) {
// 如果相等,就打印下标
System.out.println("下标:" + i);
// 结束break循环
break;
}
}
// 需求 2:求出数组nums2中所有元素的和
int[] nums2 = {11, 22, 33, 44, 22, 55};
// 遍历全部不用下标,用foreach循环
// 声明一个int变量sum装和,赋值0
int sum = 0;
for (int e : nums2) {
// 将每一个元素e累加到sum中
sum += e;
}
System.out.println("和:" + sum);
// 需求 3:求出数组nums3中所有偶数元素、奇数元素的和
int[] nums3 = {11, 22, 33, 44, 22, 55};
int evenSum = 0; // 声明一个int变量evenSum装偶数和,赋值0
int oddSum = 0; // 声明一个int变量oddSum装奇数和,赋值0
// 遍历全部不用下标,用foreach循环
for (int e : nums3) {
// 判断当前元素e是否是偶数,如果是累加到evenSum中,如果不是则累加到oddSum
if (e % 2 == 0) { // 判断e是否是偶数
evenSum += e;
} else {
oddSum += e;
}
}
System.out.println("偶数和:" + evenSum + " 奇数和:" + oddSum);
}
int[] nums = {11, 22, 33, 44, 22, 55};
System.out.println(nums); // 打印的是地址,没有意义
/*
* 需求 4:希望将该数组进行字符串拼接,这样我们就你可以打印字符串的指定格式: [元素1, 元素2, 元素3....]
* 思路:要遍历数组,将数组元素进行字符串拼接
* 步骤:
* 1. 声明一个String类型str,赋值为"[",用来拼接字符串的
* 2. 遍历数组nums,初始化条件,从下标0开始,循环结束条件到倒数第二个元素
* 每次循环,都将获取到的元素nums[i]拼接到str中,然后在继续拼接一个逗号
* 3. 循环结束后,再将最后一个元素nums[nums.length - 1]拼接上,拼接 结尾]
*/
// 1. 声明一个String类型str,赋值为"[",用来拼接字符串的
String str = "[";
// 2. 遍历数组nums,初始化条件,从下标0开始,循环结束条件到倒数第二个元素
for (int i = 0; i <= nums.length - 2; i++) {
// 每次循环,都将获取到的元素nums[i]拼接到str中
str += nums[i] + ", ";
}
System.out.println(str);
// 3. 循环结束后,再将最后一个元素nums[nums.length - 1]拼接上,拼接 结尾]
str += nums[nums.length - 1] + "]";
System.out.println("拼接后: " + str);
// 需求5:求出数组arr中的最大值
int[] arr = {11, 22, 33, 44, 22, 55};
/*
* 思路:
* 将第一个和第二个比较大小,找出最大的,保存到临时变量中,然后继续跟下一个比较,一直比较到最后一个元素,循环结束后,最大的值就找到了
*/
int max = arr[0];// 声明一个临时变量max,赋值arr第一个元素,保存的都是遍历到的最大值
// 普通for循环,下标从1开始
for (int i = 1; i < arr.length; i++) { // 下标从1开始,到最后一个元素结束
// 将当前遍历到的元素arr[i]跟临时变量max比较,如果当前元素arr[i]>max,就给max重新赋值
if (arr[i] > max) {
max = arr[i]; //就给max重新赋值为当前元素arr[i]
}
}
System.out.println("最大值:" + max);
// 需求6:求出数组arr中的最大和最小值
int max2 = arr[0]; // 声明一个临时变量max2,赋值arr第一个元素,保存的都是遍历到的最大值
int min = arr[0]; // 声明一个临时变量min,赋值arr第一个元素,保存的都是遍历到的最小值
// 普通for循环,下标从1开始
for (int i = 1; i < arr.length; i++) { // 下标从1开始,到最后一个元素结束
// 将当前遍历到的元素arr[i]跟临时变量max2比较,如果当前元素arr[i]>max2,就给max2重新赋值
if (arr[i] > max2) {
max2 = arr[i]; //就给max2重新赋值为当前元素arr[i]
}
// 将当前遍历到的元素arr[i]跟临时变量min比较,如果当前元素arr[i]<min,就给min重新赋值
if (arr[i] < min) {
min = arr[i]; //就给min重新赋值为当前元素arr[i]
}
}
System.out.println("======最大值:" + max2);
System.out.println("======最小值:" + min);
// 需求7:请将"我" "爱" "你" 存入数组,然后正着和反着输出
String[] iLoveYou = {"我", "爱", "你"};
// 正序输出
for (String s : iLoveYou) {
System.out.println(s);
}
// 反着输出
for (int i = iLoveYou.length - 1; i >= 0; i--) {
System.out.println(iLoveYou[i]);
}8、本章重点
数组声明、赋值、取值、遍历
for循环执行流程
9、数组加强练习
数组在实际工作及很多底层都有使用到,因此做一个加强练习。
完成以下关于数组相关练习题
1. 统计一个字符在字符数组中第一次出现的下标(直接输出)
2. 统计一个字符在字符数组中出现的次数(直接输出)
3. 已知这样的整型数组 int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22}; 计算出其中的奇数和以及偶数和
4. 现在有数组 double[] scores = {11, 34, 76, 77, 88, 99, 58, 97, 56};统计并打印出每一个阶段的学生人数(分段方式:0-60; 60-80;80-100)
5.翻转传入数组中的元素
例如有这样的数组 char[] arr = {'贤', '叔', '同', '学'};
调用完上面的方法之后,arr中的内容是这样的{'学', '同', '叔', '贤'};
下一章《方法》的引入和作用以及使用。