2024年java基础的传递性

java基础的传递性目录 前言 方法的参数为基本数据类型 方法的参数为引用类型 String 类型 包装类 数组 其他自定义类 总结 前言 对于 Java 初学者来说 刚学习 Java 的时候可能经常会听到调用方法时参数的值传递与引用传递 但是 实际上 Java 中方法的参数传递机制只有值传递 首先 我们要了解一个概念 栈帧 栈帧位于 java 虚拟机栈中 用于支持虚拟机进行方法的调用和方法的执行

大家好,我是讯享网,很高兴认识大家。



前言

对于Java初学者来说,刚学习Java的时候可能经常会听到调用方法时参数的值传递与引用传递。

但是,实际上Java中方法的参数传递机制只有值传递。 首先,我们要了解一个概念——栈帧。

栈帧位于java虚拟机栈中,用于支持虚拟机进行方法的调用和方法的执行。可以简单的理解为栈帧即方法。

每个方法有自己独立的栈帧。栈帧中有局部变量表、操作数栈、动态链接、返回地址等。

下面我们通过几个例子具体分析java方法的参数传递机制。

方法的参数为基本数据类型

首先我们来看下面代码:

public class ParamTransmit { public static void main(String[] args) { int i = 1; change(i); System.out.println("i = " + i); } public static void change(int j) { j += 1; } }
讯享网

程序的运行结果为:

在这里插入图片描述

当在main方法中调用change方法时,参数传递相当于将main栈帧中的参数i=1拷贝了一份给change栈帧,此时change栈帧中,变量j的值为1。然后在change方法中执行j java基础的传递性 += 1;运算,j的值变为2,change方法结束。main方法未结束,此时main栈帧中变量i的值仍为1。当传递的参数是基本数据类型时,传递的是数据值,即将参数拷贝一份到被调用方法的栈帧中。该方法中对变量的操作不影响原来栈帧中的变量的值,原栈帧中的变量不被修改。

在这里插入图片描述

方法的参数为引用类型

引用类型变量如String类型,包装类,数组和其他自定义类等。下面依次介绍。

String类型

先上代码

讯享网public class ParamTransmit { public static void main(String[] args) { String str = "hello"; change(str); System.out.println("str = " + str); } public static void change(String str) { str += "world"; } }

程序运行结果为:

在这里插入图片描述

首先,在jdk1.7之后,运行时常量池从方法区中移了出来,在堆中开辟了一块区域存放运行时常量。

并且要知道String的值是不可变的,每次对String的操作都会产生新的String对象。

因此,在上面代码中,main方法中调用change方法时,首先是将变量str的值(即运行时常量池中hello的地址)拷贝一份到change栈帧中,此时change栈帧中的变量str也是指向“hello”。

然后执行str += "world";操作,由于String值不可变,此时change栈帧中的str指向新的字符串“helloworld”,str的地址值已改变。

而此时main栈帧中str的值并没有改变,仍指向“hello”,所以main方法中输出的str仍是“hello”。

在这里插入图片描述

包装类

先上代码:

public class ParamTransmit { public static void main(String[] args) { Integer num = 200; change( num); System.out.println("num = " + num); } private static void change(Integer num) { num += 1; } }

程序运行结果为:

在这里插入图片描述

上面代码中,首先Integer num = 200;会自动装箱,先调用Integer.valueOf(200),在堆中创建一个值为200的Integer实例,并将该实例的地址赋值给num。

main方法在调用change方式时传递的是num的地址值,此时change栈帧中的num也指向值为200的Integer实例。

当执行num += 1;时,也自动装箱,先调用Integer.valueOf(201),在堆中创建一个职位201的Integer实例,并将该实例的地址赋值给change栈帧中的变量num,change方法结束。

但此时,main栈帧的num仍指向值为200的Integer实例,因此打印结果为200。

内存结构图如下:

在这里插入图片描述

注:上述内存结构图仅适用于不在-128至127之间的整数。Integer类的自动装箱机制是首先提供一个Integer cache[],用于存放-128至127的缓存。因此,若对实参及对形参操作的结果均在-128至127之间,则实参及形参应指向数组中的元素,而不是堆中新的Integer实例。

数组

直接上代码

讯享网import java.util.Arrays; public class ParamTransmit { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5}; change(arr); System.out.println("arr = " + Arrays.toString(arr)); } private static void change(int[] arr) { arr[0] += 1; }

程序运行结果为:

在这里插入图片描述

数组变量也是引用类型。main方法在调用change方法时,传递的是数组arr的地址值。

change方法内,将数组中第一个元素的值自增1,此时数组中第一个元素的值变为2。

change方法结束,main方法继续执行,此时main栈帧变量arr仍指向该数组,只不过该数组中的元素已被修改。所以输出的是被修改后的数组。

内存结构示意图如下:

在这里插入图片描述

可以引申为多维数组及数组元素为引用类型的情况。

其他自定义类

直接上代码

class MyData { int a = 10; } public class ParamTransmit { public static void main(String[] args) { MyData md = new MyData(); change(md); System.out.println("md.a = " + md.a); } private static void change(MyData md) { md.a += 1; } }

程序运行结果为:

在这里插入图片描述

main方法调用change方法时,同样是将main栈帧中的变量md的值传递到change栈帧中,此时传递的是地址值,指向堆中同一个MyData实例。

然后执行md.a += 1,此时该实例的成员变量a为11。

change方法执行完毕,main方法未结束,main栈帧中的变量md仍指向该实例,此时输出的a为11。内存结构如下图。

在这里插入图片描述

若将上面代码修改如下,会是什么结果呢?

class MyData { int a = 10; } public class ParamTransmit { public static void main(String[] args) { MyData md = new MyData(); change(md); System.out.println("md.a = " + md.a); } private static void change(MyData md) { md = new MyData(); md.a += 1; } }

程序运行结果为:

在这里插入图片描述

main方法调用change方法时,同样传递的是地址值。

然而执行md = new MyData();时,在堆中创建了一个新的实例。

此时change栈帧中的变量md的值变成了新的MyData实例的地址。

然后继续执行md.a += 1;,修改的是新的实例的成员变量。

当change方法调用结束后,main方法继续执行,此时main栈帧中md指向的仍是原来的实例,原实例的成员变量未被修改,仍是10。因此输出结果是10。

内存结构如下图。

在这里插入图片描述

总结

通过以上分析,我们可以知道java的参数传递机制是值传递。

若参数是基本数据类型,传递的是数据值;若参数是引用数据类型,传递的是地址值。

若参数是基本数据类型,对形参的操作不影响实参,因其是不同栈帧的不同变量。

若参数是引用数据类型,并且是String、包装类等。

因其对象的不可变性,对形参的操作会导致其指向新的String或包装类等对象,但不影响实参,实参仍指向原来的对象且该对象并未被修改。

若参数是引用数据类型,并且是数组、StringBuffer及其他自定义类等时,对形参的操作会影响到实参,因其指向的是同一个实例。

小讯
上一篇 2024-12-28 15:09
下一篇 2024-12-28 14:28

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/9481.html