值传递和引用传递

首先 不管下面说什么, 公论:Java 只有值传递,没有引用传递

官方的话:

值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

参数传递 可以理解当我们要调用一个方法时,我们会把指定的数值,传递给方法中的参数,这样方法中的参数就拥有了这个指定的值,可以使用该值,在方法中运算了。这种传递方式,我们称为参数传递。

我们来总结一下,值传递和引用传递之前的区别的重点是什么。

值传递 引用传递
根本区别 会创建副本(copy) 不创建副本
所以 函数中无法改变原始值 函数可以改变原始值

官方的话也是非常的官方了!

简单点说:

在此之前,我们先搞懂两个概念

实参和形参

public static void main(String[] args) {
    int a = 8; // 实参
    f(a);
}

public static void f(int a){
    System.out.println(a);  // 形参
}

实参,就是我们要传递给方法的,在方法外面

形参,就是我们方法签名上定义的参数,在方法里面

那么,值传递和引用传递的区别是什么呢?

简单粗暴来说:

对形参的修改不会影响到实参,那就是值传递,

对形参的修改能够影响到实参,那就是引用传递

例1:

  (回到图示)
    public static void main(String[] args) {
        int a = 8; // 实参
        f(a);
        System.out.println("实参:" + a);
    }

    public static void f(int a){
        a = 16;
        System.out.println("形参:" + a);
    }

/*打印结果:
    形参:16
    实参:8
    */

​ 如果我们将基本数据类型的值,传递到方法中,然后在方法内修改形参的值,最后

打印实参和形参。

​ OK!来看打印结果,可以发现,形参修改了,并没有影响到实参。这很符合值传递。

​ 我们再来看非基本数据类型,也就是对象,

public class Person {

    public String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

当我们将一个对象变量,传递到方法中,然后在方法内修改对象的属性,再打印实参和形参

例2:

  (回到图示)
public static void main(String[] args) {
    Person p = new Person("张三");
    f(p);
    System.out.println("实参:" + p);
}

public static void f(Person p) {
    p.name = "李四";
    System.out.println("形参:" + p);
}

/*
* 打印结果:
* 形参:Person{name='李四'}
  实参:Person{name='李四'}
* */

会发现实参和形参的都被修改了,这样看起来 java 好像也支持引用传递呀!

别急,你别着急!

我们再来看看这个例子,

例3:

  (回到图示)
public static void main(String[] args) {
    Person p = new Person("张三");
    f(p);
    System.out.println("实参:" + p);
}

public static void f(Person p) {
    p =new Person("李四") ;
    System.out.println("形参:" + p);
}


/*
*打印结果:
* 形参:Person{name='李四'}
* 实参:Person{name='张三'}
* 
* */

如果我们创建一个新对象,并赋值给形参,此时再打印

会发现实参和形参已经互不影响了,

要理解这些现象,我们需要搞懂。。。

在 JVM 中,划分了好几块内存区域,其中就有一个栈空间,和一个堆空间

我们创建所有的对象都存放在堆中,而基本数据类型局部变量是存放在栈中的

(来看刚才的例1)

当传递基本数据类型时,是将数据创建了一个副本,传递到方法中,那自然形参修改也不会影响到实参,符合值传递。

当操作对象时就要注意了,对象是存放在堆中的。

我们拿到的只是对象的引用,通过对象的引用,就可以操作对象。

这也就是说为什么说,java 数据类型,分为两种,一种是基本数据类型,一种是引用数据类型。

我们来回顾 (第二个例子(点击))

当对象引用传递给方法时,其实是创建了一个引用副本,实参和形参都指向了同一个对象,所以通过形参引用操作对象时,显得实参好像改变了。

但实参本身是没有改变的,因为实参就是原先的那个引用嘛,就是一个遥控器,电视机内容改变了,遥控器本身又没有改变。

(例3)

​ 所以我们将形参重新赋值的时候,实参是不会受到任何影响的。此时形参和实参指向不同的对象。

总结:

​    java 完全就是值传递的,如果是基本数据类型,那就复制一份值传递给形参,如果是引用数据类型,那就将引用复制一份传递给形参,形参始终拿到的都是一份副本,无论如何,都无法通过形参改变实参,毕竟形参只是操作的副本而已。

内容参考 RudeCrab

posted @   走马!  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示
主题色彩