第四天 数组【悟空教程】
第04天 Java基础
第1章 数组
1.1 数组概念
软件的基本功能是处理数据,而在处理数据时,必须先进行数据持有,将数据持有之后,再对数据进行处理。我们将程序中可以临时存储数据的部分叫做容器。
Java当中具有持有数据功能的容器中,数组是最基本的,也是运算速度最快的。
1.2 数组的定义格式
数组是引用类型的一种,其使用方式与引用类型类似,均使用new关键字创建对象为变量赋值。
-
格式1:数据类型[] 数组名 = new 数据类型[元素个数或数组长度];
-
格式2:数据类型 数组名[] = new 数据类型[元素个数或数组长度];
-
注意:这两种定义做完了,数组中是没有元素值的。如何对数组的元素进行初始化呢?
示例:int[] arr = new int[5];
还有其他格式如下:
int[] arr = new int[]{20,5,100,30,5}
int[] arr = {20,5,100,30,5}
int arr[] = new int[4];//源码中经常会看到的定义方式
1.3 数组初始化
-
概述
-
Java中的数组必须先初始化,然后才能使用。
-
所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。
-
-
数组的初始化方式
-
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
-
静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
-
1.3.1 数组内元素均有默认初始化值
在创建数组对象后,数组中元素会被自动赋予一个默认值,这个过程叫做默认初始化。根据元素类型的不同,默认初始化的值也是不一样的。具体如下表所示。
表2-1 元素默认值
数据类型 |
默认初始化值 |
byte、short、int、long |
0 |
float、double |
0.0 |
char |
一个空字符(空格),即’\u0000’ |
boolean |
false |
引用数据类型 |
null,表示变量不引用任何对象 |
1.3.2 数组的初始化(动态初始化)
-
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
-
格式:数据类型[] 数组名 = new 数据类型[数组长度];
-
数组长度其实就是数组中元素的个数。
-
举例:
-
int[] arr = new int[3];
-
解释:定义了一个int类型的数组,这个数组中可以存放3个int类型的值
-
-
1.4 访问数组元素
-
直接打印数组名,打印的是数组堆内存中的地址
-
数组中的每个元素都是有编号的,编号是从0开始的,最大的编号就是数组的长度-1
-
用数组名和编号的配合我们就可以获取数组中的指定编号的元素
-
数组底层是依次将数据进行编号后直接通过编号访问(线性序列)的。这个编号叫做索引。
-
格式:数组名[编号] -- 数组名[索引]
-
数组名称为arr,索引为0,1,2
-
获取数组中元素的格式:
-
arr[0]获取数组中的第一个元素
-
arr[1]获取数组中的第二个元素
-
arr[2]获取数组中的第三个元素
-
-
如:
int[] arr = {20,5,100,30,5};
arr[0]访问的为20,arr[2]访问的100。
这里的”访问”包含以下两个动作:获取值与赋值。如:
为元素赋值: arr[1] = 33; 则第2个元素5会被33替代。
获取元素的值: int x = arr[3]; 则x的值为30。
使用数组名.length可以获取数组长度。
/*
数组:它是引用数据类型的一种,它是存放同种数据类型数据的容器(集合)
数组定义格式:
数据类型[] 数组名 = new 数据类型[数据长度/元素个数];
访问数组中指定编号的元素:数组名[索引]
给数组中的元素赋值: 数组名[索引] = 数据值;
使用数组名.length可以获取数组长度。
直接打印数组名是获取了数组的堆内存地址值(内存图详细了解)
*/
public class Demo02Array{
public static void main(String[] args){
//定义一个长度为3的整数数组
int[] arr1 = new int[3];
//int[] arr2 = new int[]{1,2,3,4,5};//有几个元素,长度就为几
int[] arr2 = {1,2,3,4,5};
// 索引 0 1 2 3 4
//访问arr2数组中第一个元素
//System.out.println("数组的第一个元素: " +arr2[0]);
int x = arr2[0];
System.out.println("数组的第一个元素: " + x);
//给数组中的元素赋值: 数组名[索引] = 数据值;
arr2[1] = 100;
System.out.println("arr2[1]: " +arr2[1]);
int length1 = arr1.length;
System.out.println("数组arr1的长度:" +length1);
int length2 = arr2.length;
System.out.println("数组arr1的长度:" +length2);
System.out.println(arr1);//[I@104c575
System.out.println(arr2);//[I@3fa5ac
char[] ch = new char[4];
System.out.println(ch);//[I@3fa5ac
//定义一个长度为10的String类型数组
//String[] arr2 = new String[10];
}
}
直接打印数组名是获取了数组的堆内存地址值(内存图详细了解)
1.5 数组的注意事项
1.5.1 数组的长度是固定的
数组在创建对象过程当中,必须指定数组长度,无法创建对象进而无法给变量赋值。
1.5.2 一个数组中只能存储一种类型的数据
在数组的定义格式中有显式地写出该数组中存储的数据类型,所以一个数组只能存储同一种数据类型。(在多态的讲解后,我们会有新的理解)
1.5.3 数组运行期报错
在使用数组时,因为不当的操作,我们可能会通过编译,但是在运行期间遇到一些程序报错类似这样编译时不报错,运行期报错的错误叫运行时错误
数组最常见的两个运行时错误:空指针异常和数组索引越界异常
1.5.3.1 空指针异常
编程语言中对空的处理与我们平常所理解的略有不同。这里我们区分两种空的不同
变量完全没有值:
定义了变量根本没有值:int a; int[] b
这样根本没有赋值过的变量是无法使用的。数组也是一种数据类型,可以指定变量,没有赋值是不能使用的。
变量有值,但值为null:
定义了变量并且赋值了,但是值是空值,是常量。这种情况只针对于引用数据类型,基本数据类型不成立。
int a = null; 编译失败
int[] arr = null; 正常赋值
当使用int[] arr = null给arr赋值时,变量arr作为数组名通过编号访问数组元素时编译不报错,运行时报运行错误NullPointerException空指针异常
1.5.3.2 数组索引越界异常
当数组中不存在该索引却访问该索引时,运行时报错:
ArrayIndexOutOfBoundsException 数组索引越界
/*
数组的注意事项:
1.数组在创建对象过程当中,必须指定数组长度,否则无法创建对象进而无法给变量赋值。
2.在数组的定义格式中有显式地写出该数组中存储的数据类型,所以一个数组只能存储同一种数据类型。(在多态的讲解后,我们会有新的理解)
3.在创建数组对象后,数组中元素会被自动赋予一个默认值,这个过程叫做默认初始化。根据元素类型的不同,默认初始化的值也是不一样的。
数组运行期错误:
空指针异常:给数组变量赋值的时候,赋值成null,数组不指向一个堆内存的地址,索引会报NullPointerException
数组索引越界:访问了不存在的索引
*/
public class Demo03Array{
public static void main(String[] args){
//1.数组在创建对象过程当中,必须指定数组长度,否则无法创建对象进而无法给变量赋值。
//定义一个长度为5的int类型数组
//int[] arr = new int[];//错误: 缺少数组维
int[] arr = new int[5];
//2.一个数组只能存储同一种数据类型。
//arr[0] = "hello";// 错误: 不兼容的类型
arr[0] = 18;
System.out.println(arr[0]);//18
//int有默认的初始化值 0
System.out.println(arr[1]);//0
System.out.println(arr[2]);//0
System.out.println(arr[3]);//0
System.out.println(arr[4]);//0
String[] arr2 = new String[3];
arr2[0] = "詹姆斯";
System.out.println(arr2[0]);//詹姆斯
//String有默认的初始化值 null
System.out.println(arr2[1]);//null
System.out.println(arr2[2]);//null
System.out.println(arr2[3]);//ArrayIndexOutOfBoundsException: 3
/*
double[] arr3;
System.out.println(arr3[0]);//错误: 可能尚未初始化变量arr3
*/
//int a = null;// 错误: 不兼容的类型
//double[] arr3 = null;
//System.out.println(arr3[0]);//NullPointerException
}
}
1.6 数组的内存解释
1.6.1 内存分区
内存是计算机临时存储数据的区域,我们会将内存在逻辑上分配成不同区域方便对数据进行分类高效管理。
-
寄存器:最快的存储区域直接与CPU打交道,是程序员无法控制的计算区域。
-
堆栈:又叫栈,仅次于寄存器。用于存储局部变量。
-
堆:通用内存池,用于存放所有引用数据类型对象。每个对象均有地址,且有默认初始化值。
-
常量存储区域:用于存放永远不会被改变的值。
1.7 Java中的内存分配
Java 程序在运行时,需要在内存中的分配空间。
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
内存分区:
-
栈 又叫栈,仅次于寄存器。用于存储局部变量
-
局部变量是定义在方法中或者语句中的变量
-
局部变量使用完毕,立即回收
-
-
堆 通用内存池,用于存放所有引用数据类型对象。每个对象均有地址,且有默认初始化值。New出来的东西。
-
每一个对象都有首地址值,是一个十六进制的地址
-
每一个对象内的数据都有默认值
-
byte,short,int,long 0
-
float,double 0.0
-
-