值传递OR引用传递?大部人都答错了!

简介: 值传递OR引用传递?大部人都答错了!

Java 是值传递还是引用传递?这是 Java 中比较基础的一道常见面试题,但对于这道问题的大部分答案都是错的,大部人会这样回答这个问题:

在 Java 中,如果传递的是基本数据类型,那么就是值传递;而如果传递的是对象或数组的话,那么就是引用传递。

然而,这个答案是错的!

定义描述

值传递和引用传递是编程中参数传递给方法时的两种方式,它们的定义如下:

  1. 值传递(Pass by Value):在值传递中,实际参数的值被复制一份,然后将这份复制的值传递给函数或方法的相应参数。因此,函数或方法内对参数所做的任何修改都不会影响到实际参数的值。
  2. 引用传递(Pass by Reference):在引用传递中,传递给方法的是实际参数的引用(或地址)。这意味着方法内对参数所做的任何修改都会直接影响到实际参数。

需要注意的是,有些编程语言,如 C++ 提供了真正的引用传递机制,允许你直接传递变量的引用,并且可以在函数或方法中改变这个引用的指向。而在 Java 中,即使是对象,也是通过值传递的,只不过这个值是对象引用副本(而非对象引用本身)

正确结论

在 Java 中,(传递参数时)无论是基本数据类型还是对象(或数组),使用的都是值传递的方式。只是对于对象(或数组)而言,传递的值是对象引用副本,而非对象引用本身。

在 Java 中,只有值传递没有引用传递

举个例子

例如 Integer 是包装类对象吧?它不是基本数据类型对吧,当我们传递 Integer 对象时,在新方法所做的所有修改,并不会影响原对象本身,具体示例代码如下:

public class PassExample {
   
   
    public static void main(String[] args) {
   
   
        Integer number = new Integer(10);
        method(number);
        System.out.println("number:" + number); // 输出:number:10
    }
    public static void method(Integer number) {
   
   
        number = 20; // 修改 num 的值,不会影响原始变量的值
    }
}

以上程序的执行结果如下:

从上述结果可以看出,当传递的是 Integer 对象时,其依然是值传递,所以在 Java 语言中,并没有引用传递。

因此,无论是基础数据类型,还是引用数据类型(对象),都为值传递,而非引用传递。

特殊的例子

有人说:不对啊,磊哥,你看我传递数组时,改变传递的数组就会影响原数组啊,具体示例如下:

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

以上程序的执行结果为:

调用方法前:磊哥

方法中修改为:磊神

调用方法后:磊神

这样就出问题了,当传递了数组之后,明显是“引用传递”,而非值传递,这到底是怎么回事?

别着急,当我们把新方法中的代码做了以下调整之后,运行结果又不一样了,如下代码所示:

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

以上程序的执行结果为:

调用方法前:磊哥

方法中修改为: 神

调用方法后:磊哥

你会发现,当我们在新方法中仅仅添加了一行“n = new char[2];”代码时,它又变成了值传递,这是怎么回事?

原因分析

如果是引用传递,那么我在新方法中无论如何修改,那么都应该是影响原对象才对,而刚才我稍微调整了代码之后就发现其并非引用传递,而是值传递,这是因为当传递数组时,其传递的是“引用副本”,而非真正的引用对象(也就是其本身)

也就说,当传递数组时,其实传递的是“引用副本”,如下图所示:

然而,在调用了“n = new char[2];”代码之后,给变量在堆上创建了新对象,此时就不再使用原来的引用副本了,这个时候,再修改新方法中的变量就不影响原变量了,如下图所示:

所以,在 Java 中,只有值传递,它始终传递的都是副本,而非原(引用)对象

小结

在 Java 中,(传递参数时)无论是基本数据类型还是对象(或数组),使用的都是值传递的方式。只是对于对象(或数组)而言,传递的值是对象引用副本,而非对象引用本身。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

相关文章
|
C++
32 C++ - 运算符重载碰上友元函数
32 C++ - 运算符重载碰上友元函数
31 0
|
7月前
|
存储 安全 Java
Java方法的值传递技术详解
Java方法的值传递技术详解
44 3
|
程序员 编译器 C语言
指针太乱傻傻分不清?教你如何正确快速理解/函数指针/数组参数、指针参数/函数指针数组【C语言/指针/进阶/程序员内功修炼】【中】
指针太乱傻傻分不清?教你如何正确快速理解/函数指针/数组参数、指针参数/函数指针数组【C语言/指针/进阶/程序员内功修炼】【中】
47 0
|
7月前
|
存储 安全 编译器
C语言详解指针(指针海洋的探索,将传值与传址刻在心里)
C语言详解指针(指针海洋的探索,将传值与传址刻在心里)
46 0
|
7月前
|
C++
c++关于值传递,指针传递,引用传递这几个方面还会存在误区
c++关于值传递,指针传递,引用传递这几个方面还会存在误区
38 0
|
7月前
|
C++
C++函数与值传递
C++函数与值传递
36 0
细说值传递、引用传递和地址传递
细说值传递、引用传递和地址传递
|
编译器 C++
<C++>深浅拷贝与初始化列表技巧你真的会了吗
<C++>深浅拷贝与初始化列表技巧你真的会了吗
165 0
|
Java
Java面向对象-方法的值传递和引用传递
Java面向对象-方法的值传递和引用传递
121 0
|
存储 C语言
指针妙用之将函数中形参的值传递给实参
指针妙用之将函数中形参的值传递给实参
下一篇
DataWorks