数组
1.定义:存储数据的容器
2.注意事项:某一类型的数组只能存储同类型的数据,或者范围比数组类型小的数据
3.数据类型复习
4.数组的定义格式
A.数据类型[] 变量名 //较常用
实例:int[] array; //此处定义的是数组类型的变量,还未进行初始化,不能直接使用
B.数据类型 变量名[]
实例:int array[];
5.数组的初始化
Java中数组必须初始化之后才能使用,分为动态初始化和静态初始化
5.1 动态初始化
在初始化的时候需要手动指定数组的长度,系统会为数组容器分配初始值,不同类型的数组的默认值不同
整数型数组:默认值为0;
浮点型数组:默认值为0.0;
布尔型数组:默认值为false;
字符型数组:默认值为空字符();
引用数据类型数组:默认值为null;
其中引用数据类型是指引用、记录了地址值的变量,该变量所对应的数据类型,例如:
int[]arr=new int[3];
此段代码中,数组变量arr的类型不是int,而是int[]这个整体,int[]就叫做引用型数据类型;
A.格式
数据类型[] 数组名 = new 数据类型[数组的长度];
数据类型 数组名[] = new 数据类型[数组的长度];
B.实例
package com.myidea.arrayPackage;
public class TestArray {
public static void main(String[] args) {
int[] array = new int[5];
System.out.println(array);
/*此处打印的结果是:[I@1b6d3586;
[代表是数组类型的变量,I代表的是数组容器中存储的数据类型,
@是分隔符,分开两边的数据,1b6d3586是十六进制内存地址
*/
}
}
5.2 静态初始化
初始化时,就可以指定数组要存储的元素,系统会自动计算出数组长度
A.格式
数据类型[] 变量名 = new 数据类型[数据1,数据2,数据3,......];
实例:int[] arr = new int[]{1,2,3};
简化格式:
数据类型[]变量名={数据1,数据2,数据3};
实例:int[] arr ={1,2,3};
B.案
5.3 数组初始化动态和静态的区别
-
动态初始化:手动指定数组的长度,由系统给出默认初始化值
-
静态初始化:手动指定数组元素,系统会根据元素个数计算出数组的长度
使用场景:
5.3.1 动态初始化适用于只明确元素个数,不明确具体数值的场景
例:使用数组存储键盘录入的3个整数
分析:由于不知道五个整数分别是什么,无法在定义时直接赋予相应的值,所以只能使用动态初始化
5.3.2 动态初始化适用于数据已经明确的场景
例:将3个已知数据录入数组
分析由于数据已知,可以直接将数据赋值给数组
package com.myidea.arrayPackage;
import java.util.Scanner;
public class TestArray02 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3}; //数据已知,赋值给数组后,系统会自动计算存入数据的个数
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
int[] arr01 = new int[3];
//数据未知,但知道个数,先定义长度为三的数组为接下来存储3个数据做准备
System.out.println(arr01);
System.out.println(arr01[0]);
System.out.println(arr01[1]);
System.out.println(arr01[2]);
for(int i = 0;i<=2;i++) { //用循环语句重复键入指定个数的数据
Scanner sc = new Scanner(System.in);
arr01[i] =sc.nextInt();
}
System.out.println(arr01[0]);
System.out.println(arr01[1]);
System.out.println(arr01[2]);
}
}
6.数组中经常犯的错误
1.索引越界
访问了数组中不存在的索引,造成越界问题报错
示例:
public class TestArray01 {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
arr[0]=0;
arr[1]=1;
arr[2]=2;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[20]);//数组只定义了3个长度,此处却指向到数组的第21个索引空间
}
}
程序运行后会报错:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 20
at com.myidea.arrayPackage.TestArray01.main(TestArray01.java:15)
(TestArray01.java:15)提示的是出现问题的类文件和行数;
ArrayIndexOutOfBoundsException 指你访问了一个不存在的索引
2.空指针异常
null:空值,引用数据类型的默认值,表示不指向任何有效对象
数组地址被赋予null值,访问的数组记录的地址值被替换为空值,已经不在指向堆内存所开辟的空间,造成访问空指针异常
示例
package com.myidea.arrayPackage;
public class TestArray01 {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
arr[0]=0;
arr[1]=1;
arr[2]=2;
arr = null;
//此时arr所记录的地址值已经被空值null所替代,再根据arr所记录的地址值访问空间会报错
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr);
}
}
程序运行后会报错:
Exception in thread "main" java.lang.NullPointerException
at com.myidea.arrayPackage.TestArray01.main(TestArray01.java:13)
(TestArray01.java:13) 记录的是错误的类文件和行数
NullPointerException 指的是空指针异常
7.动态获取数组中元素的个数
格式: 数组名.Length
示例:
int arr[] = new int[]{1,2,3,...};
System.out.print(arr.Length);//此处打印的即为数组内元素的个数
8.数组整体实战
package arrayPackage;
import java.util.Scanner;
/*
需求:在比赛中,有六个评委为参赛的选手打分,分数为0-100的整数分。
选手的最后得分为去掉一个最高分和一个最低分之后的4个分数的平均值。
分析:1.需要用键盘录入六位评委的打分,需要导入Scanner的包;
2.键盘录入的分需要存在数组中,数组已知要存入六个评委的数据,故用动态初始化定义数组长度
3.键盘录入的分数需要为0-100之间的整数,所以录入之后需要用if语句对键入值做一个判断,不符合要求则报错
4.报错后要求重新输入需要用到死循环
5.分数都存到数组之后需要遍历出所有数据,找出最大最小值,用其他值求出平均数,遍历用for循环排序
*/
public class TestArray2 {
public static void main(String[] args) {
double[] arr1 = new double[6];
Scanner sc = new Scanner(System.in);
for (int i = 0; i < arr1.length; i++) {
cycle:
while (true) {
/*
死循环没有必要,条件控制语句是i++,只要将else后面加上一个i--就可以在输入不符合要求时一直将输入卡在这一步
for(int i = 0;i <arr1.length;i++) {
System.out.println("请输入打分");
arr1[i] = sc.nextDouble();
if (arr1[i]==(int)arr1[i] && arr1[i]>=0 && arr1[i]<=100){
break cycle;
}else{
i--;
System.out.println("请输入正确的分数");
}
}
*/
System.out.println("请输入打分");
arr1[i] = sc.nextDouble();
if (arr1[i] == (int) arr1[i] && arr1[i] >= 0 && arr1[i] <= 100) {
break cycle;
} else {
System.out.println("请输入正确的分数");
}
}
}
for (int j = 0; j < arr1.length; j++) {
System.out.println(arr1[j]);
}
double max = arr1[0], min = arr1[0], sum = 0;
for (int k = 0; k < arr1.length; k++) {
if (max < arr1[k]) {
max = arr1[k];
}
}
System.out.println(max);
for (int k = 0; k < arr1.length; k++) {
if (min > arr1[k]) {
min = arr1[k];
}
}
System.out.println(min);
for (int k = 0; k < arr1.length; k++) {
sum += arr1[k];
}
System.out.println(sum);
int avg = (int) ((sum - max - min) / 4);
System.out.println(avg);
}
}
9.方法参数引用数据类型的传递
方法引用数据类型的定义格式:
public static void 方法名(int 数组名[]){
方法体;
}
实例:
package com.huly.mypacdage05;
public class methodTest05 {
public static void main(String[] args) {
int arr[] = new int[]{1,2,3};
System.out.println(arr[1]);
array01(arr); //将数组的地址值赋予被调用方法的引用数据类型参数,也就是数组
System.out.println(arr[1]);
}
public static void array01(int[] arr){
/*
数组的数据类型属于引用数据类型,定义格式为int[] 数据名;数组名和主方法里的不干涉,调用此方法时还会再堆内存中开辟空间,但方法执行完毕之后开辟的空间就会消失,开辟的空间在程序中用不到,因为调用参数的时候会将地址值赋给此方法中的数组,这样此数组自己开辟的
空间就用不到了,此数组和主方法里面的数组同时指向堆内存中同一个空间,在这个方法里操作数组空间内的元素会直接改变主函数中数组的元素
*/
System.out.println(arr[1]);
arr[1] = 3;
}
}