integer是值传递还是引用传递_Java只有值传递

    可能有很多小伙伴都知道Java是值传递,但是又说不出个所以然,我也是这样,于是去看了一些博客,下面来一个简单的总结。

     首先说结论:Java中只有值传递,没有引用传递

    这里涉及到值传递和引用传递两种传递机制:

    值传递(pass by value):是指在调用方法(或者函数)时,将实际参数复制一份传递到方法(或者函数)中,这样在函数中如果对形式参数进行修改,将不会影响到实参。

    引用传递(pass by reference):在调用方法(函数)时,将实参的地址直接传递到函数中,那么在函数中对形参进行修改,将影响到实参。

    下面来看看上面定义的重点:

值传递引用传递
根本区别复制实参不复制实参
修改的是什么?形参
实参改变否?不改变改变

        实参和形参的概念我想不必再提了,大家应该都懂。

    可能看到这里有的小伙伴会说:基本数据类型是值传递,引用数据类型是引用传递

    以前我也是这么认为,但是实际上是错误的。我们再看看我们修改的是什么?

    形参啊!你传递了一个对象进去,结果修改的是对象的属性,对象的属性是你传的形参吗?即使你把对象的所有属性都改了,那也不是形参啊!!!!

        为了方便理解,我们先看下图:

e7a9191d399f63588b62258a62279070.png

    基本数据类型在栈中保存的就是变量,但是引用数据类型在栈中保存的是地址,凭什么你传给形参的时候传栈里面的值,但是你修改的时候要修改堆里面的内容?

     所以我们应该修改的形参也应该是栈中的数据。

      下面我们直接来看代码验证我的结论:

 public class Demo04 {    public static void main(String[] args) {        int a = 2;        System.out.println(a);//结果为2        //值传递        change(a);        System.out.println(a);//结果为2    }    public static void change(int a){        a = 10;    }}

        对于这里的结果大家应该没有异议。接下来看这段代码:

public class Demo05 {    public static void main(String[] args) {        String str = "学渣很忙";//String可是引用数据类型哟        System.out.println(str);//学渣很忙        change(str);        System.out.println(str);//学渣很忙    }    public static void change(String str){        str = "张三";        //上面这句话等价于下面这句话,忽略入不入字符串常量池        //str = new String("张三");    }}

    为什么对于引用数据类型String来说,前后的结果并没有改变呢?看了change方法的注释你大概就懂了,修改形参的值就是new了一块新的内存空间,也就是说我们修改的是将栈中原来保存的地址值复制了一份给形参,然后形参中修改了这个地址值。内存图如下

45d4b79be1f16b6826ebfa45b8063c92.png

        需要明确的一点是,我们在被调方法(函数)中操作的是形参,而复制的一份形参也是压入栈中,所以修改形参应该是修改栈中的值。

       然后就是修改形参的值,对于基本数据类型就可以直接在栈中修改;对于引用数据类型需要通过保存在栈中的地址值找到堆中的数据。但是这并不影响我们修改形参,如果此时你修改的不是形参而是堆中的属性,那当然会对属性产生影响。但是我们要修改形参,也就是new 一个新的内存空间,把new出来的地址值赋值给形参,这才是真正的修改形参。

    最后是结果比较,如果你真的是修改的形参,你在内存图中看看原来的实参有没有变化呢?答案是实参没有改变。

    我的结论得到了验证:Java中只有值传递,没有引用传递。小伙伴们可以试一下对0x1234进行修改,然后画画内存图作为练习;下面是我给出的答案:

public class Demo06 {    public static void main(String[] args) {        Student student = new Student();        student.name = "张三";        student.age = 21;        System.out.println("修改形参前的student:"+student);        change(student);        System.out.println("修改形参后的student:"+student);        changeAttribute(student);        System.out.println("修改属性后的student:"+student);    }    //这里才是修改的形参    public static void change(Student student){        student = new Student();        student.name = "王麻子";        student.age = 35;        System.out.println("change方法中的student:"+student);    }    //这样修改是修改的属性,而不是参数    public static void changeAttribute(Student student){        student.name = "李四";        student.age = 12;    }}class Student{    String name;    int age;    @Override    public String toString() {//用来输出对象的名字和年龄的        return "name=" + name + ", age=" + age;    }}

    这是运行结果:

cf860d98aed5101c47ae3f02cdd6fba1.png

 66cd3c4d8f6ece8dc1aee47fbe10ba79.png

 内容到这儿就结束啦,初学小白,如有错误烦请各位大佬及时指出!感谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值