zoukankan      html  css  js  c++  java
  • Java只有值传递

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

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

     

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

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

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

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

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

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

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

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

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

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

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

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

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

    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

    了一块新的内存空间,也就是说我们修改的是将栈中原来保存的地址值复制了一份给形参,然后形参中修改了这个地址值。内存图如下

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

    然后就是修改形参的值,对于基本数据类型就可以直接在栈中修改;对于引用数据类型需要通过保存在栈中的地址值找到堆中的数据。但是这并不影响我们修改形参,如果此时你修改的不是形参而是堆中的属性,那当然会对属性产生影响。但是我们要修改形参,也就是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;
        }
    }

    这是运行结果:

     

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

  • 相关阅读:
    web开发之web 验证码--- webqq 机器人
    赛星软件---智能视频分析事件检测
    模式识别之双目立体视觉---双目立体视觉相关介绍
    安卓项目之微信公众好---初体验
    《数学分析》视频
    单目和双目模式识别---游戏控制
    多媒体开发之音频编码---ffmpeg 编码aac
    PC如何访问手机网址
    linux shell实现守护进程 看门狗 脚本
    grep用法详解:grep与正则表达式
  • 原文地址:https://www.cnblogs.com/xzhm/p/12965334.html
Copyright © 2011-2022 走看看