Java是值传递还是引用传递?区别是什么?


Java技术债务
在Java中参数的传递主要有两种: 值传递引用传递

值传递

实参传递给形参的是值

形参和实参在内存上是两个独立的变量

对形参做任何修改不会影响实参

也就是说:在方法调用时,传入方法内部的是实参引用的拷贝,因此对形参的任何操作都不会影响到实参。

public class Main {
        public static void main(String[] args) {
            int b =20;
						// 实参  实际上的参数
            change(b);
            System.out.println(b);
        }
        public static void change(int a){//形参  形式上的参数
            a = 100;
        }
}

结果:20

Java是值传递还是引用传递?区别是什么? - Java技术债务

形参只是实参创建的一个副本,副本改变了,原本当然不可能跟着改变;

引用传递

实参传递给形参的是参数对于堆内存上的引用地址

实参和形参在内存上指向了同一块区域

对形参的修改会影响实参

public class Main {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        list1.add(2);
        list1.add(3);
        list1.add(4);
        list1.add(5);
        System.out.println(list1);
        change(list1);
        System.out.println(list1);
    }

    public static void change(List<Integer> list2) {
        list2.add(6);
    }
}

结果:
[2, 3, 4, 5]
[2, 3, 4, 5, 6]

可以在IDEA上debug以下,如图:

Java是值传递还是引用传递?区别是什么? - Java技术债务

Java是值传递还是引用传递?区别是什么? - Java技术债务

从debug的结果可以看出,创建出来的list1的对象ID是484,list2的对象ID也是484,传过去的参数其实是list1的对象ID**。**

Java是值传递还是引用传递?区别是什么? - Java技术债务

由于引用传递,传递的是地址,方法改变的都是同一个地址中的值。

原来list1指向0xxx地址,有4个数字,后来在change方法对0xxx地址添加了一个数字,变成了5个数字,地址都是指向同一块内存。

两者区别

  • 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量.
  • 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。 所以对引用对象进行操作会同时改变原对象.

Java到底是值传递还是引用传递

在Java方法中参数列表有两种类型的参数,基本类型和引用类型。

  • **基本类型:**值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值。
  • **引用数据类型:**指针存放在局部变量表中,调用方法的时候,副本引用压栈,赋值仅改变副本的引用。但是如果通过操作副本引用的值,修改了引用地址的对象,此时方法以外的引用此地址对象当然被修改。(两个引用,同一个地址,任何修改行为2个引用同时生效)。

这两种类型都是将外面的参数变量拷贝一份到局部变量中,基本类型为值拷贝,引用类型就是将引用地址拷贝一份。

网上众说纷纭,说什么的都有,但是我倾向于Java的传递是值传递

如果传的时基本数据类型,只改变传递的副本不会改变原变量;如果传递的时对象类型,传递的变量是对象类型的地址,修改此地址指向的对象值 = 直接去对地址指向的对象,但是不会修改原对象的引用

比如:交换两个对象

public class Main {
 
    public static void swapObjectReference(ParamObject object1, ParamObject object2) {
        ParamObject temp = object1;
        object1 = object2;
        object2 = temp;
    }
 
    public static void main(String[] args) {
        ParamObject a = new ParamObject(true, 1);
        ParamObject b = new ParamObject(false, 2);
        System.out.println("a : " + a + " b : " + b);
        swapObjectReference(a, b);
        System.out.println("a : " + a + " b : " + b);
    }
}

结果:

a : ParamObject{flg=true, num=1} b : ParamObject{flg=false, num=2}

a : ParamObject{flg=true, num=1} b : ParamObject{flg=false, num=2}

有了上面的知识之后,我们会发现这个方法中的引用地址交换,只不过是一个把戏而已,只是对方法中的两个局部变量的对象引用值进行了交换,不会对原变量引用产生任何影响的。

Java是值传递还是引用传递?区别是什么? - Java技术债务

当然,完全说Java是值传递也不是严谨的,毕竟值传递的概念是:在方法调用时,传入方法内部的是实参引用的拷贝,因此对形参的任何操作都不会影响到实参。但是Java中有引用类型也就是包装类型的对象传递,传递其实是地址,在方法中修改形参会影响到实参的,因为形参和实参指向堆中同一块内存。

可以借鉴之前看到的一个解释:

java 使用的是一种名为值传递的求值策略,这种策略在传值过程中会复制实参的引用,并将这份拷贝传入到方法形参中,所以对形参的任何重赋值操作都不会对实参产生影响。


--------------------------------------欢迎叨扰此地址---------------------------------------

本文作者:Java技术债务
原文链接:https://cuizb.top/myblog/article/1677079385
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java技术债务

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值