}
如上述代码,该语句会便利数组 array,并且每次都会将数组的元素保存在变量 x 中
- 法三(使用 Arrays 类中的 toString 方法)
// 使用 Arrays 类前先导入它的包
import java.util.Arrays;
public class TestDemo{
public static void main(Strings[] args){
int[] array = {1, 2, 3};
String ret = Arrays.toString(array);
System.out.println(ret);
}
}
// 打印结果为:[1, 2, 3]
Arrays 类 中 toString 的功能就是将当前的数组转换成字符串的形式返回,返回值就是字符串
上述遍历方式各有各的特点,至于什么时候用哪一遍历方式,据情况而定
1. 认识 JVM 内存区域划分
我们知道,一个 Java 文件的执行需要先通过编译变成字节码文件,字节码文件再痛过 Java 虚拟机运行
因为字节码文件是被 JVM 转换成平台所能执行的形式所运行的,那么 JVM 到底是怎样的呢?
JVM 本质其实就是一个用 C/C++ 代码实现的软件,它的内存被划分五块为如图所示的样子
那么这里面的各块都分别有啥意义呢?
- 程序计数器:是一个很小的空间,保存下一条执行的指令地址(通俗的来说就是你本来在敲代码,你老妈喊你去吃饭,但你吃完饭后还要回来执行完你没敲完的代码)
- Java 虚拟机栈:这就是我们平常说的栈,它重点是存储局部变量(像上面创建的数组
int[] array = {1, 2, 3}
的存储地址的引用就是保存在这里)
- 本地方法栈:本地方法栈与虚拟机栈的作用类似,只不过保存的内容是 Native 方法的局部变量(在有些版本的 JVM 的实现中(例如 HotSpot),本地方法和虚拟机栈是一起的)
- 堆:这就是我们平常说的堆,是 JVM 所管理的最大的内存区,使用 new 创建的对象都是在堆上保存(例如
int[] array = new int[]{1, 2, 3}
)
- 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据(方法编译出的字节码就是保存在这里)
- 运行时常量池:这个是方法区的一部分(上述未画出),存放字面量(字符串常量)与符号引用(注意:从 JDK 1.8 开始,运行时常量池在堆上)
补充(Native 方法)
JVM 是一个基于 C++ 实现的程序,在 Java 程序执行过程中,本质上也需要调用 C++ 提供的一些函数和操作系统底层进行一些交互。因此在 Java 开发中也会调用到一些 C++ 实现的函数
既然知道了 JVM 的一些知识点,那么我们就可以对我们上述三种创建数组的代码做一个存储区域分析
int[] array1 = {1,2,3,4,5};
int[] array2 = new int[5];
int[] array3 = new int[]{1, 2, 3, 4, 5};
分析结果如图
- 我们知道,array1、array2、array3 是局部变量,所以它们会在栈上开辟一块内存。
- Java 中的数组都属于对象,而对象保存在堆中(对象就是一个实体,比如实际生活中的花草树木,或者上述代码中的
{1, 2, 3, 4, 5}
或者用更加规范的方式 new 出来的对象)
- 而保存在堆上的对象又有着自己的内存。上述三个局部变量又是引用变量(即这个变量里面存储的是一个地址),它们将会存储对应将每个对象的元素的首地址
- 按照术语来说,用array1举例就是:array1 就是一个引用,它引用了一个对象(指向一个对象)
2. 数组传参以及被调用的过程
我们直接通过一个图片来感受下面代码中数组传参以及被调用的过程
public static void main(String[] args){
int[] array = {1, 2, 3};
print(array;)
}
public static void print(int[] array){
for(int x : array){
System.out.print(x + " ");
}
}
// 打印结果为:1 2 3
3. 理解引用类型
从上图我们可以知道,参数传数组类型,实参和形参其实都是引用,共同指向同一个对象。
因此如果形参将对象的值改变,那么实参的值也随即改变。可以用一个代码举例
public static void main(String[] args){
int[] array = {10, 20};
System.out.print(“交换前:array[0] = " + array[0] + " array[1] =” + array[1]);
System.out.println();
swap(array);
System.out.print(“交换后:array[0] = " + array[0] + " array[1] =” + array[1]);
}
public static void print(int[] array){
int tmp = array[0];
array[0] = array[1];
array[1] = tmp;
}
// 结果为:
// 交换前:array[0] = 10 array[1] = 20;
// 交换后:array[0] = 20 array[1] = 10;
为了在理解上更加清晰,我们再举一个例子
public static void main(String[] args){
int[] array1 = {1, 2, 3};
int[] array2 = array1;
}
我们可以说 array2 这个引用指向 array1 这个引用吗?不能!这其实是表述有误!
引用不能说指向引用,引用只能说指向另一个引用所指的对象。故我们应该理解成:array2 这个引用指向了 array1 这个引用所指向的对象
小结
- 引用类型本质上只是存了一个地址
- Java 将数组设定成引用类型,这样后续进行数组参数传参,其实只是将数组的地址传到函数的形参中。这样可以避免对整个数组进行拷贝,减小开销
- Java 中的引用类型有:String、数组、类、接口、枚举、抽象类
4. 认识 null
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
时减轻大家的负担。**
[外链图片转存中…(img-jHxLplx6-1710848652958)]
[外链图片转存中…(img-vGGmXu5w-1710848652958)]
[外链图片转存中…(img-dXzJJTXG-1710848652959)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-Lf77NRBO-1710848652959)]