文章目录
- 一、数组的介绍
- 二、数组的定义
- 2.1 静态初始化
- 2.2 动态初始化
- 三、常见操作
- 3.1 访问数据
- 3.2 修改数据
- 3.3 常见问题
- 四、数组内存图(难点)
- 4.1 前置知识
- 4.2 执行流程
- 五、结语
一、数组的介绍
Java中的数组是一种基本的数据结构,它能够存储固定数量的、相同类型的元素。数组中的每个元素都通过一个索引(或位置)来访问,索引通常是从0开始的整数
- 固定大小:一旦创建,数组的长度不可变。
- 连续内存分配:数组元素在内存中
二、数组的定义
Java中定义数组主要有以下两种方式
2.1 静态初始化
如果你已经知道数组中要存储哪些具体元素,可以使用静态初始化。这时不需要指定数组长度,它会根据初始化元素的数量自动决定。
这里有些同学可能碰到,[]中括号放在数组名后面,其实都是一样,我这边建议[]中括号放在数据类型
public class Main {public static void main(String[] args) {// 静态初始化: 简写格式(推荐)// 格式:数据类型[] 数组名 = {元素1,元素2,元素3,......}int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 静态初始化:完整格式// 格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,......}int[] arr1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};// 这两句话的意思都是:创建一个 int类型的数组,数组中存放着1, 2, 3, 4, 5, 6, 7, 8, 9数据}
}
2.2 动态初始化
当你只知道数组的长度,但不确定具体元素值时,可以使用动态初始化。
public class Main {public static void main(String[] args) {/* 动态初始化:完整格式格式:数据类型[] 数组名 = new 数据类型[数组的长度]*/int[] arr = new int[10]; // 这句话的意思是:创建一个 int类型的数组,长度为10}
}
因为这种方式只指定数组的长度,元素会被赋予类型的默认值
- 整数类型:0
- 小数类型:0.0
- 字符类型:‘/u0000’ (空格)
- 布尔类型:false
- 引用类型:null (除了上面四类8种数据类型外,其他都是引用类型)
三、常见操作
数组元素需要通过索引访问
- 索引也叫下标
- 索引是从0开始的,逐渐加1,直到数组长度-1为止
3.1 访问数据
需求:定义一个数组,获取数组的第一个元素和最后一个元素
public class Main {public static void main(String[] args) {// 1、定义数组int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 2、访问第一个元素System.out.println(arr[0]); // 1// 3、访问最后一个元素System.out.println(arr[8]); // 9}
}
现在有一个问题,如果这个数组的长度你不知道,当然我们现在都知道访问第一个元素下标都是0,那最后一个元素因为你不知道数组长度所以你就不知道下标
public class Main {public static void main(String[] args) {// 1、定义int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 2、访问第一个元素System.out.println(arr[0]); // 1// 3、访问最后一个元素// 获取数组的长度:数组名.length// 解释:arr.length会获取到数组的长度,因为下标是从0开始的,所以要减1,// 如果不减1,意思是arr[9],这就会造成数组中没有这个下标,你还要去访问,就会抛出索引越界异常System.out.println(arr[arr.length - 1]);; // 9}
}
3.2 修改数据
需求:定义一个数组,修改数组的第一个元素和最后一个元素,并打印出来
import java.util.Arrays;public class Main {public static void main(String[] args) {// 1、定义数组int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 2、修改第一个元素arr[0] = 11;// 3、修改最后一个元素arr[arr.length - 1] = 99;// 4、打印数组// 解释:Arrays是java提供的一个针对于数组的一个工具类,里面有很多方法// Arrays.toString(数组名):这会把数组以字符串的方式打印出来System.out.println(Arrays.toString(arr)); // [11, 2, 3, 4, 5, 6, 7, 8, 99]}
}
3.3 常见问题
数组索引越界异常:java.lang.ArrayIndexOutOfBoundsException
原因:当你访问的下标超出数组的长度时就会报出这个错误
public class Main {public static void main(String[] args) {// 1、定义数组int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 2、访问数组[9]的数据System.out.println(arr[9]);// Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 9 out of bounds for length 9// at Main.main(Main.java:7)// 翻译:你有一个异常,类型是java.lang.ArrayIndexOutOfBoundsException,原因是索引9超出了数组的长度9// 在Main类中main方法第7行}
}
四、数组内存图(难点)
4.1 前置知识
我们要理解数组的内存图,要先搞明白Java内存分配中的堆、栈。
- 堆:存储的是对象或数组,在Java中通过new关键字创建的对象都存储在堆内存中;
- 栈:方法运行时使用的内存,比如程序的主入口main()方法运行时就会进入到方法栈中执行。
当你理解什么是堆、栈后,你还要理解什么是地址值。
public class Main {public static void main(String[] args) {// 1、定义数组int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 2、打印数组的地址值System.out.println(arr); // [I@4eec7777}
}
-
解释:1. [:是指这个对象是数组类型2. I:是指数组中存放的是整数类型,D是小数类型3. @:间隔符号,没什么特殊含义4. 4eec7777:是这个对象的地址值,就是在你要使用这个数组,你就要去堆中根据这个地址值去找到这个数组再操作实际,我们会把这一整个叫地址方便一些,你只要知道4eec7777才是真实的地址值就可以了
4.2 执行流程
public class Main {public static void main(String[] args) {// 1、定义数组 arrint[] arr = new int[2]; // [I@4eec7777}
}
- 首先,栈内存会去加载main()方法,此时会将 int[] arr = [I@4eec7777 放在栈内存中
- 因为根据new关键字的都会在堆内存中产生,堆内存会创建一个地址值为:[I@4eec7777 的int类型的数组,此时数组的数据都是默认值,长度是2
- 之后的每次的操作如果要操作数组的元素的话(比如:访问数据,修改数据),会去堆内存中根据数组的地址值查询数组,然后根据下标去操作数组,产生的结果,会返回到栈内存中。
场景:我要修改arr的值,arr2会改变吗,为什么
import java.util.Arrays;public class Main {public static void main(String[] args) {// 定义数组int[] arr = new int[2]; // [I@4eec7777int[] arr2 = arr; // [I@4eec7777// 修改数组的值arr[0] = 1;// 打印两个数组System.out.println(Arrays.toString(arr)); // [1, 0]System.out.println(Arrays.toString(arr2));// [1, 0]}
}
答:会改变,因为操作的两个数组的地址是一样的
五、结语
这篇博客大概3500字左右,希望能对你有所帮助,如果有什么问题欢迎留言,我这边有时间就会回。
如果觉得我写的不错的小伙伴,可以帮我点个赞,收藏一下,如果还有什么希望我出的教程可以留言,我会参考。