• 解惑4:java是值传递还是引用传递


    一、概述

    曾经纠结了很久java的参数传递方式是什么样的,后面粗略的了解了一鳞半爪以后有了大概的印象:“传参数就是值传递,传对象就是引用传递”,后面进一步查找了相关资料和文章以后,发现这么理解是不正确的。

    这里先放结论:

    • java中参数的传递可以理解为都是值传递
    • 基础数据类型传递的是值的拷贝
    • 对象类型是共享对象传递,传递的是地址的拷贝

    二、形参和实参

    要理解参数的传递就必须先理解形参和实参:

    • 形参:就是形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。

      形参只有在方法被调用的时候,虚拟机才会分配内存单元,在方法调用结束之后便会释放所分配的内存单元。

      因此,形参只在方法内部有效,所以针对引用对象的改动也无法影响到方法外。

    • 实参:就是实际参数,用于调用时传递给方法的参数

    举个例子:

    public static void main( String[] args ) {
        String string = "Hello";
        //string是实际参数
        sout(string);
    }
    
    public static void sout(String str){
        //str为形式参数
        System.out.println(str);
    }
    

    三、值传递和引用传递与共享对象传递

    1.值传递和引用传递

    理解了实参和形参,以及java对应的数据类型,我们就可以理解值传递和引用传递了。

    • 值传递:方法调用时,实际参数的被传递给对应的形式参数,函数接收的是原始值的一个copy, 此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值

    • 引用传递/址传递:方法调用时,实际参数的地址被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址。在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象

    对于这两种方式,网上有一个非常形象的图:

    2.共享对象传递

    但是java的传值策略有点类似于两者的结合,是共享对象传递

    • 共享对象传递:先获取到实际参数的地址,然后将其复制,并把该地址的拷贝传递给被调函数的形式参数。因为参数的地址都指向同一个对象,所以我们称也之为"传共享对象",所以,如果在被调函数中改变了形式参数的值,调用者是可以看到这种变化的。

    这也是之所以说java也是值传递的原因,共享对象传递实际上也是对实参进行拷贝然后赋给形参,但是操作针对的对象不是值而是地址

    由于传递的是地址的拷贝,所以如果你在方法中将这个地址指向了新的对象,实际上是没有任何对方法外是没有任何作用的,举个例子:

    public static void main( String[] args ) {
        Person p = new Person();
        System.out.println("main中:" + p.hashCode());
        change(p);
        System.out.println("main中:" + p.hashCode());
    }
    
    public static void change(Person person){
        person = new Person();
        System.out.println("change中:" + person.hashCode());
    }
    
    //输出
    main中:692404036
    change中:1554874502
    main中:692404036
    

    可以看到在main方法中输出的hashCode指向的都是同一个对象,而change中指向了另一个,可以这么理解:

    • p为指向了第一个Person对象的地址
    • 把p拷贝了一份得到p‘,这里的p’就是change方法中的形参p
    • change中p指向了一个新的Person对象,在change这个函数范围里p指向的就是new出来的第二个Person对象的地址
    • 由于change中的p实际上是main中p的拷贝p‘,所以在change里p'指向的改变对main中的p不会有任何影响

    四、总结

    你在福建有座仓库,给自己配了一把钥匙

    1.三种传递:

    • 值传递:你建了一座一模一样的仓库给别人
    • 引用传递:把你家仓库的钥匙给了别人
    • 共享对象传递:把你家仓库钥匙复刻了一把给别人

    2.共享对象传递的特点:

    • 拷贝的地址与原地址指向同一个内存对象:别人用你复刻的钥匙一样能进出你的仓库
    • 拷贝地址引用对象的改变不影响原地址的引用对象:老王在福建泉州也盖了个一模一样仓库,钥匙和你的一模一样,虽然你的仓库比较有名,但是唯独在泉州提到仓库大家都想到的是老王的仓库。你说这把钥匙能开仓库,在泉州大家想到是这把钥匙能开老王的仓库,在其他城市大家想到是能开你的仓库
  • 相关阅读:
    121.买卖股票 求最大收益1 Best Time to Buy and Sell Stock
    409.求最长回文串的长度 LongestPalindrome
    202.快乐数 Happy Number
    459.(KMP)求字符串是否由模式重复构成 Repeated Substring Pattern
    326.是否为3的平方根 IsPowerOfThree
    231.是否为2的平方根 IsPowerOfTwo
    461.求两个数字转成二进制后的“汉明距离” Hamming Distance
    206.反转单链表 Reverse Linked List
    448. 数组中缺少的元素 Find All Numbers Disappeared in an Array
    常见表单元素处理
  • 原文地址:https://www.cnblogs.com/Createsequence/p/13439392.html
Copyright © 2020-2023  润新知