数组的引入
数组的概念:
数组是一个容器,存放一组相同数据类型变量的容器
回顾变量的初始化
a.声明: 告诉计算机开辟多大的内存空间
b.赋值: 编译器翻译变量所对应的地址值,通过地址值,将数据保存到地址对应的位置去
c.使用: 读取变量对应的地址,取出数值使用
数组
a.声明:告诉计算机开辟多大的连续的内存空间
b.赋值: 系统会默认赋值也可以自己赋值
c.使用
初始化格式
数据类型[] 数组名 = new 数据类型[数组的大小];
数据类型可以是八大基本数据类型,也可以是引用类型
数组名满足变量的命名规则,一般都是复数
new 开辟内存空间,在堆区开辟空间
数组大小: 容器的大小
访问数组中的元素:
数组名[下标/索引];
下标从0开始~数组的长度-1
java.lang.ArrayIndexOutOfBoundsException: 3
异常名称: 数组越界
产生原因: 访问数组的下标不在 0~数组的长度-1之间
解决办法: 检查范围
java.lang.NullPointerException
异常名称: 空指针异常
产生原因: 对象没有new,就访问对象成员
解决办法: 找对null值对象并且创建对象
数组的内存分析
声明一个变量就是在内存空间划出一块合适的空间,类似声明一个数组就是在内存空间划出一串连续的空间
这里需要注意的是:
1.标识符:数组的名称,用于区分不同的数组
2.数组元素:在数组中存放的数据
3.元素下标:对元素进行编号,从零开始,数组中的每个元素都可以通过下标来访问
4.元素类型:数组元素的数据类型
数组的特点
a.数组本身也是一个变量,既然是变量(局部变量),那么在栈区开辟空间,先声明再赋值再使用
b.数组的数据类型可以是八大基本数据类型和引用类型,数组本身是引用类型
c.创建数组我们需要使用到new,那么new出来的在堆区开辟,所以数组会同时在栈区和堆区开辟空间
d.如果一个数组没有指向堆区某块内存地址,这个时候数组变量为null,如果使用这个变量会出现空指针异常
e.如果一个数组访问了不存在的索引,会出现数组越界
数组的使用
声明数组
作用:告诉计算机数据类型是什么
格式:
数据类型 数组名[ ] ;
数据类型[ ] 数组名 ; (推荐格式)
注意:声明数组时不规定数组长度
例子:
int[ ] score1; //Java成绩
int score2[ ]; //android成绩
String[ ] name; //学生姓名
数组的初始化
数组的初始化
静态初始化
格式一: 数据类型[] 数组名 = {元素1,元素2,元素3,元素4,元素5,...元素n};
格式二: 数据类型[] 数组名 = new int[]{元素1,元素2,元素3,元素4,元素5,...元素n};
动态初始化
数据类型[] 数组名 = new 数据类型[数组的大小];
可以采用以下三种方式初始化
1.逐个初始化
2.通过键盘输入
3.通过随机数初始化
静态初始化和动态初始化的区别?
静态初始化: 初始化的同时为每一个元素给出初始值,不需要指定数组的长度,系统会根据元素的个数去动态计算数组的长度
动态初始化: 初始化的系统来为数组赋初始值,默认值是堆区的特点的默认值,但是必须由我们指定数组的长度
当形式参数是引用类型的时候的传递过程
八大基本类型传递满足类型转换
引用类型
数组
类
接口
值传递和引用传递
1.值传递的本质传递的是数值本身,引用传递的本质传递的是地址
2.如果传递的是地址,那么通过地址改变了堆区空间的数值,将会影响到所有指向该堆区的引用
分配空间
作用:告诉计算机分配几个连续的空间
格式:数据类型[ ] 数组名 = new 数据类型[大小] ;
声明数组并分配空间
例子:
1.score = new int[30]; 内存图如下:
2.avgAge = new int[6];
3.name = new String[30];
赋值
作用:向分配的格子里放数据
例子:score[0] = 89;
score[1] = 79;
score[2] = 76;
这种方式复制太慢
快速赋值法:
方法1: 边声明边赋值
int[ ] score = {89, 79, 76};
int[ ] score = new int[ ]{89, 79, 76};
注意:这里右边不能声明数组的长度
方法2:动态地从键盘录入信息并赋值
Scanner input = new Scanner(System.in);
for(int i = 0; i < 30; i ++){
score[i] = input.nextInt();
}
处理数据
计算5位学生的平均分
定义这样个数组:
int [ ] score = {60, 80, 90, 70, 85}; 内存中结构如下图:
方式一:通过数组下表直接访问
double avg;
avg = (score[0] + score[1] + score[2] + score[3] + score[4])/5;
方式二:数组的length属性
int sum = 0;
double avg;
for(int i = 0; i < score.length; i++){
sum = sum + score[i];
}
avg = sum / score.length;
数组常见错误
1.编译出错,没有写明数组的大小
2.编译出错,数组越界
3.编译出错,创建数组并赋值的方式必须在一条语句中完成
数组内存图
1.类加载
2.JVM调用main()方法
数组的内存分配
内存分为:
a.栈区: 先进后出,类似于子弹夹,一般用来给局部变量开辟空间
b.堆区: 用于存储new出来的对象
堆区创建出来的对象都会有地址值,而数组变量就是用来存放这个地址的
凡事new出来的对象都有默认值
byte short int long 0
float double 0.0
char '\u0000'
boolean false
引用类型 null
堆区一旦被赋值为null的时候,原来的内存空间不会被立刻回收,而是在垃圾回收器空闲的时候回收
int[] arr = new int[5];
arr = null;
c.方法区
静态区
常量池
数组的遍历
遍历: 获取数组中的每一个元素
public static void printArr(int[] arr){
for(int i= 0; i < arr.length; i++){
System.out.println(ar[i]);
}
}
数组的动态快速初始化 (键盘输入 + 数组的动态初始化 + 数组的遍历)
Scanner input = new Scanner(System.in);
System.out.println("请输入学生的人数:");
double num = input.nextDouble();
double[] arr = new double[num];
for(int i = 0; i < arr.length; i++){
System.out.print("请输入第" + (i+1) + "个学生的成绩");
arr[i] = input.nextDouble();
}
input.close();