面试官:Java是值传递还是引用传递?
创始人
2025-07-06 13:11:00
0

开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文。

说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型。

1、值类型

通俗意义上来说,所谓的值类型指的就是 Java 中的 8 大基础数据类型:

  • 整数型:byte、int、short、long
  • 浮点型:float、double
  • 字符类型:char
  • 布尔类型:boolean

从 JVM 层面来讲:所谓的值类型指的是在赋值时,直接在栈中(Java 虚拟机栈)生成值的类型,如下图所示:

2、引用类型

引用类型是指除值类型之外的数据类型,比如:

  • 接口
  • 数组
  • 字符串
  • 包装类(Integer、Double...)

从 JVM 的层面来讲,所谓的引用类型是指,在初始化时将引用生成栈上,而值生成在堆上的这些数据类型,如下图所示:

PS:关于包装类为什么是引用类型?我们后面的文章会单独讲,记得关注:Java中文社群

3、值传递

值传递(Pass By Value)指的是方法传参时,传递的是原内容的副本,因此对副本进行如何修改都不会影响原内容。

实现代码如下:

public class PassTest {
    public static void main(String[] args) {
        int age = 18;
        System.out.println("调用方法前:" + age);
        intTest(age);
        System.out.println("调用方法后:" + age);
    }

    private static void intTest(int age) {
        age = 30;
        System.out.println("方法中修改为:" + age);
    }
}

程序的执行结果为:

调用方法前:18

方法中修改为:30

调用方法后:18

从上述结果可以看出,在方法中修改参数并未影响原内容,我们把这种传参方式称之为值传递。

4、引用传递

引用传递(Pass By Reference)指的是方法传参时,传递的是参数本身,因此对参数进行任意修改都会影响原内容。

模拟“引用传递”的实现代码如下:

public class PassTest {
    public static void main(String[] args) {
        char[] name = {'磊', '哥'};
        System.out.println("调用方法前:" + new String(name));
        paramTest(name);
        System.out.println("调用方法后:" + new String(name));
    }
    private static void paramTest(char[] n) {
        n[1] = '神';
        System.out.println("方法中修改为:" + new String(n));
    }
}

程序的执行结果为:

调用方法前:磊哥

方法中修改为:磊神

调用方法后:磊神

从上述的结果可以看出在 paramTest 方法中修改了参数之后,在 main 方法中再打印参数时,发现参数的值也跟着发生了改变,那么似乎我们可以得出结论,Java 中貌似也有“引用传递”,然而实事并如此,我们接着看。

5、真假“引用传递”

我们给上面的代码添加一行,如下所示:

public class PassByValue {
    public static void main(String[] args) {
        char[] name = {'磊', '哥'};
        System.out.println("调用方法前:" + new String(name));
        paramTest(name);
        System.out.println("调用方法后:" + new String(name));
    }
    private static void paramTest(char[] n) {
        n = new char[2]; // 添加此行代码
        n[1] = '神';
        System.out.println("方法中修改为:" + new String(n));
    }
}

程序的执行结果为:

调用方法前:磊哥

方法中修改为:神

调用方法后:磊哥

从上述结果可以看出,当我们在 paramTest 方法中添加 new char[] 之后,“引用传递”就突然变值传递了?为什么?

这是因为,在 Java 语言中本质上只有值传递,也就说 Java 的传参只会传递它的副本,并不会传递参数本身。

前面那个带引号的“引用传递”其实只是传递了它的引用副本,如下图所示:

PS:《Java虚拟机规范》中对  Java 堆的描述是:“所有的对象实例以及数组都应当在堆上分配”。

所以我们在调用 new char[] 之后,可以看出 n 对象有了新地址,而原内容并未被修改,如果按照引用传递的思路来看的话,不管执行任何方式的修改都会改变原内容,因此我们可以更加确认 Java 语言中只有值传递,如下图所示:

总结

通过本文的内容,我们可以得出:在 Java 语言中只有值传递,方法传参时只会传递副本信息而非原内容。我们还知道了基础数据类型会直接生成到栈上,而对象或数组则会在栈和堆上都生成信息,并将栈上生成的引用,直接指向堆中生成的数据,如下图所示:

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...