一、前言
记录时间 [2024-05-03]
系列文章简摘:
Java 笔记 01:Java 概述,MarkDown 常用语法整理
Java 笔记 02:Java 开发环境的搭建,IDEA / Notepad++ / JDK 安装及环境配置,编写第一个 Java 程序
Java 笔记 11:Java 方法相关内容,方法的设计原则,以及方法的定义和调用
Java 笔记 12:Java 方法的相关使用,方法重载、参数传递,以及递归等内容
更多 Java 相关文章,请参考上面专栏哦。
本文讲述 Java 数组相关知识,包括数组的声明和创建、以及数组的简单使用。此外,文章对 Java 内存进行分析,从内存的角度分析了数组创建的过程。
二、数组概述
Java 中的数组是一种数据结构,用于存储同一类型的多个元素。
数组在 Java 中被定义为一个对象,具有固定的长度,并且可以容纳各种数据类型,包括原始数据类型和引用数据类型。
- 数组是相同类型数据的有序集合;
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成;
- 每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问;
- 数组的下标从 0 开始。
使用数组可以避免定义多个重复的同种类型变量。
三、数组声明和创建
在 Java 中,声明数组和创建数组可以一起完成,也可以分开进行。
1. 数组声明
必须先声明数组变量,然后才能在程序中使用数组。声明数组变量的语法是指定数组类型和数组名称。下面是声明数组变量的语法:
// 首选方法
dataType[] arrayRefVar;
// 另一种方法,效果相同
dataType arrayRefVar[];
// 例如,声明一个整型数组变量
int[] myArray;
这两种形式都可以用来声明数组变量,它们是等价的,没有功能上的区别。
但通常建议使用 dataType[] arrayRefVar;
的形式,因为它更符合 Java 编程的传统风格,并且更容易让人理解。
2. 数组创建
在 Java 中,使用 new
操作符来创建数组是一种常见的做法。new
操作符用于在堆内存中动态创建对象或数组实例。
创建数组语法如下:
// 声明和创建同时完成
// arraySize 指定数组长度
dataType[] arrayRefVar = new dataType[arraySize];
// 先声明,后创建
dataType[] arrayRefVar;
arrayRefVar = new dataType[arraySize];
// 例如,创建一个长度为 5 的整型数组
// 可以存放 5 个 int 类型的数字
int[] myArray = new int[5];
在这个例子中,new
操作符创建了一个长度为 5 的整型数组,并将其引用赋值给了 myArray
变量。这个数组会在堆内存中被动态分配空间。
创建数组时需要指定数组的长度。
四、数组简单使用
1. 数组索引
在 Java 中,数组索引用于访问数组中的元素。数组索引从 0 开始,因此第一个元素的索引是 0,第二个元素的索引是 1,以此类推。
可以使用方括号 []
来指定数组中的索引位置。
示例代码如下:
int[] myArray = {10, 20, 30, 40, 50};
// 访问数组中的第一个元素(索引为 0)
int firstElement = myArray[0]; // firstElement 的值为 10
// 访问数组中的第三个元素(索引为 2)
int thirdElement = myArray[2]; // thirdElement 的值为 30
在这个例子中,myArray[0]
表示访问数组 myArray
中的第一个元素,而 myArray[2]
表示访问数组中的第三个元素。
需要注意的是,如果尝试访问超出数组范围的索引位置,将会导致 ArrayIndexOutOfBoundsException
异常。因此,在使用数组时应当确保索引值在合法的范围内。
2. 数组长度
在 Java 中,可以使用数组的 length
属性来获取数组的长度。这个属性返回数组中元素的数量,即数组的大小。
示例代码如下:
// 创建并初始化数组
int[] myArray = {10, 20, 30, 40, 50};
// 获取数组的长度,即 5
int arrayLength = myArray.length;
在这个例子中,myArray.length
返回数组 myArray
中元素的数量,即 5。
length
是数组的属性,而不是方法,因此不需要使用括号。- 这个属性对于确定数组的大小,以及遍历数组非常有用。
- 数组的长度是固定的,一旦创建了数组并分配了空间,就不能再改变它的长度。
3. 数组初始化
数组的初始化可以分为静态初始化和动态初始化两种方式。
其中,动态初始化包含默认初始化。
静态初始化
在静态初始化中,可以在声明数组的同时为其赋初值。它的语法简洁,适用于已经知道数组初始值的情况。
静态初始化时,不需要指定数组的大小,编译器会根据提供的初始值自动确定数组的长度。
普通类型的静态初始化,示例代码如下:
// 声明并静态初始化一个整型数组
int[] myArray = {10, 20, 30, 40, 50};
在这个例子中,myArray
是一个整型数组,它包含了 5 个元素,并且每个元素的值分别为10、20、30、40 和 50。
引用类型的静态初始化
静态初始化对于引用类型的数组也同样适用,不需要显式指定数组的大小,编译器会根据提供的初始值自动确定数组的长度。
对于引用类型的数组,静态初始化方式与基本类型数组类似。可以在声明数组时直接为其赋予初始值,示例代码如下:
// 声明并静态初始化一个字符串数组
String[] myArray = {"apple", "banana", "orange"};
在这个示例中,myArray
是一个字符串数组,包含了3个元素,分别是 “apple”、“banana” 和 “orange”。
引用其他类的对象
如果想要在静态初始化数组时引用其他类的对象,可以像下面这样做:
// 假设有一个名为 Person 的类
class Person {
String name;
int age;
// 构造函数
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 在静态初始化中引用 Person 类的对象
Person[] people = {
new Person("Alice", 25),
new Person("Bob", 30),
new Person("Charlie", 35)
};
在这个例子中:
people
是一个Person
类型的数组,包含了三个Person
对象;- 每个对象都通过
new Person(...)
创建并初始化; - 每个
Person
对象都有一个名字name
和年龄age
属性。
这样就可以在静态初始化数组时引用其他类的对象了。
动态初始化
动态初始化数组是在声明数组后,使用 new
关键字为数组分配内存空间,并为数组元素赋初始值的一种方式。
相比于静态初始化,动态初始化更加灵活,可以在运行时确定数组的大小以及元素的值。
需要注意的是,动态初始化的数组长度必须是一个非负的整数值。
示例代码如下:
// 声明一个整型数组
int[] myArray;
// 使用 new 关键字动态初始化数组,并指定数组的长度为 5
myArray = new int[5];
// 为数组元素赋值
myArray[0] = 10;
myArray[1] = 20;
myArray[2] = 30;
myArray[3] = 40;
myArray[4] = 50;
在这个例子中:
- 首先声明了一个整型数组变量
myArray
; - 然后使用
new
关键字为其分配了一个长度为 5 的内存空间; - 之后,通过索引为数组元素赋值。
这种方式下,可以在运行时确定数组的大小,也可以根据具体需求为数组元素赋值。
默认初始化
在 Java 中,如果声明了一个数组但没有对其进行显式初始化,那么 Java 会对数组进行默认初始化。
默认初始化,也叫隐式初始化,是指给数组的元素赋予初始值,这个初始值取决于数组元素的类型。
需要注意的是,在使用数组之前,最好对其进行显式初始化,以避免出现意外的错误。
对于基本数据类型的数组,如果没有进行显式初始化,Java 会将数组的每个元素初始化为该基本数据类型的默认值。
例如:
- 整型数组的默认值为 0
- 浮点型数组的默认值为 0.0
- 布尔型数组的默认值为 false
- 字符型数组的默认值为 ‘\u0000’(空字符)
示例代码如下:
// 整型数组的默认值为 0
int[] intArray = new int[3];
System.out.println(Arrays.toString(intArray)); // 输出:[0, 0, 0]
// 浮点型数组的默认值为 0.0
double[] doubleArray = new double[3];
System.out.println(Arrays.toString(doubleArray)); // 输出:[0.0, 0.0, 0.0]
// 布尔型数组的默认值为 false
boolean[] booleanArray = new boolean[3];
System.out.println(Arrays.toString(booleanArray)); // 输出:[false, false, false]
// 字符型数组的默认值为 '\u0000'(空字符)
char[] charArray = new char[3];
System.out.println(Arrays.toString(charArray)); // 输出:空字符
对于引用数据类型的数组,默认值为 null
。
示例代码如下:
// 引用数据类型的数组,默认值为 null
String[] stringArray = new String[3];
System.out.println(Arrays.toString(stringArray)); // 输出:[null, null, null]
4. 数组元素赋值
在 Java 中,数组元素赋值的方式有两种:索引或初始化。
如果数组中的元素没有被赋初值,那么它的默认值为 0。
通过索引为数组元素赋值:
可以通过索引来为数组元素赋值。可以使用方括号 []
加上索引来指定要赋值的元素位置,然后将新值赋给该位置。
示例代码如下:
int[] myArray = new int[5]; // 创建一个长度为5的整型数组
// 为数组元素赋值
myArray[0] = 10; // 下标从 0 开始,给第一个元素赋值为 10
myArray[1] = 20;
myArray[2] = 30;
myArray[3] = 40;
myArray[4] = 50;
在这个例子中,通过 myArray[索引]
的形式,为数组 myArray
中的每个元素赋了一个值。
索引从 0 开始,因此 myArray[0]
表示数组中的第一个元素,myArray[1]
表示第二个元素,以此类推。
初始化赋值:
如果已经在声明数组时进行了初始化,也可以在初始化的同时为数组元素赋值,例如:
// 创建并初始化数组
int[] myArray = {10, 20, 30, 40, 50};
这样的话,数组的每个元素都被赋了初始值。
五、案例分析
1. 计算数组所有元素和
要计算数组中所有元素的和,可以使用一个循环来遍历数组,并将每个元素的值加起来。
下面是一个计算数组所有元素和的示例代码:
int[] myArray = {10, 20, 30, 40, 50};
int sum = 0;
// 遍历数组并计算所有元素的和
for (int i = 0; i < myArray.length; i++) {
sum += myArray[i];
}
System.out.println("数组所有元素的和为:" + sum);
在这个例子中:
- 首先创建了一个整型数组
myArray
,然后初始化了它。 - 接下来,定义一个变量
sum
用来存储所有元素的和,并初始化为 0。 - 然后,使用一个
for
循环遍历数组myArray
,将每个元素的值加到sum
中。 - 最后,输出数组所有元素的和。
六、内存分析
进行内存分析时,可以通过各种工具和技术来监视和分析程序的内存使用情况,包括但不限于 JVM 内置的工具(如 jvisualvm、jconsole)、第三方工具(如 VisualVM、YourKit Java Profiler)以及分析内存转储文件(Heap Dump)等。
1. Java 内存分析
在 Java 中进行内存分析通常涉及以下几个方面:
- 堆内存(Heap Memory): 堆内存是用于存储对象实例的地方。
- 所有通过
new
关键字创建的对象都存储在堆内存中,比如数组; - 可以被所有的线程共享,不会存放别的对象引用;
- 堆内存的大小可以通过 JVM 启动参数进行设置;
- 垃圾回收器负责在堆内存中回收不再使用的对象以释放内存空间。
- 所有通过
- 栈内存(Stack Memory): 栈内存用于存储方法调用和局部变量。
- 存放基本变量类型:包含这个基本类型的具体数值;
- 引用对象的变量:存放这个引用在堆里面的具体地址;
- 每个线程都有自己的栈内存,用于存储线程的方法调用栈和局部变量;
- 方法调用时,方法的参数和局部变量会被分配到栈内存中;
- 当方法执行完毕时,栈帧会被弹出栈,释放内存空间。
- 方法区(Method Area): 方法区是存储类信息、常量、静态变量等数据的地方。
- 可以被所有的线程共享;
- 包含了所有的 class 和 static 变量;
- 在方法区中存储的内容包括类的字节码、方法和字段信息、运行时常量池等;
- 方法区在 JVM 启动时被分配,一般大小固定。
2. 数组创建过程
接下来绘图分析数组创建时,在内存中完成了哪些步骤。
代码中的流程
在代码中,我们完成了 3 个步骤:声明、创建、赋值。
// 1. 声明一个整型数组变量
int[] myArray;
// 2. 创建一个长度为 5 的整型数组
int[] myArray = new int[5];
// 3. 为数组元素赋值
myArray[0] = 10; // 下标从 0 开始,给第一个元素赋值为 10
myArray[1] = 20;
myArray[2] = 30;
myArray[3] = 40;
myArray[4] = 50;
内存中体现
如图所示,在内存中,这 3 个步骤一一对应。
步骤 1:
声明一个整型数组变量 myArray
,变量 myArray
被压入栈中。
// 1. 声明一个整型数组变量
int[] myArray;
在内存中的体现:
步骤 2:
创建一个长度为 5 的整型数组,在堆中开辟一片空间给它。空间中可以存放 5 个 int
型数据,索引下标从 [0] 开始。数组元素默认赋值为 0。
// 2. 创建一个长度为 5 的整型数组
int[] myArray = new int[5];
在内存中的体现:
步骤 3:
为数组元素赋值,给第一个元素赋值为 10,第二个为 20,依此类推。
// 3. 为数组元素赋值
myArray[0] = 10; // 下标从 0 开始,给第一个元素赋值为 10
myArray[1] = 20;
myArray[2] = 30;
myArray[3] = 40;
myArray[4] = 50;
在内存中的体现:
七、总结
本文讲述 Java 数组相关知识,包括数组的声明和创建、以及数组的简单使用。此外,文章对 Java 内存进行分析,从内存的角度分析了数组创建的过程。
一些参考资料
狂神说 Java 零基础:https://www.bilibili.com/video/BV12J41137hu/
TIOBE 编程语言走势: https://www.tiobe.com/tiobe-index/
Typora 官网:https://www.typoraio.cn/
Oracle 官网:https://www.oracle.com/
Notepad++ 下载地址:https://notepad-plus.en.softonic.com/
IDEA 官网:https://www.jetbrains.com.cn/idea/
Java 开发手册:https://developer.aliyun.com/ebook/394
Java 8 帮助文档:https://docs.oracle.com/javase/8/docs/api/