精华内容
下载资源
问答
  • 1、关于值传递与引用传递的定义 值传递:是指在调用函数时,将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,就不会影响到实际参数 如下图所示,当传递参数之前会将参数进行复制,函数中修改了...

    1、关于值传递

    值传递:是指在调用函数时,将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,就不会影响到实际参数

    如下图所示,当传递参数之前会将参数进行复制,函数中修改了参数,不会影响实际参数
    在这里插入图片描述
    值传递是对于是对基本数据而言,例如下面例子,number没有改变。

    public class Test01 {
        public static void main(String[] args) {
            int number = 10;
            new Test01().change(number);
            System.out.println(number);
        }
    
        public void change(int a){
            a+=1;
        }
    }
    

    在这里插入图片描述

    2、关于引用传递

    引用传递:是指在调用函数时,将实际参数的地址传递到函数中,那么在函数中对参数进行修改,将会影响到实际参数

    引用数据类型分为两个部分,引用变量和对象,这两个部分放在不同的地方,引用变量在栈中,而对象是放在堆内存中的,引用变量指向对象。
    如下图所示,当传递参数之前会将参数进行复制,但是复制的是引用变量,复制后的引用变量还是指向内存中的同一对象,所以引用传递中,函数修改了参数会影响实际参数
    在这里插入图片描述
    引用传递是对于引用数据类型而言,例如对于User类姓名的修改,会改变对象的name。

    public class Test01 {
        public static void main(String[] args) {
            User user = new User("小明", 12);
            new Test01().change(user);
            System.out.println(user);
        }
    
        public void change(User a){
            a.setName("小张");
        }
    }
    

    在这里插入图片描述


    注意点,引用类型中的String的值是放在常量池中,我们改变副本的值不会影响到原来的值。
    在这里插入图片描述

    例如在change放发中改变了副本的值,但是原来的str字符串不会改变。

    public class Test01 {
        public static void main(String[] args) {
            String str = "hello";
            new Test01().change(str);
            System.out.println(str);
        }
    
        public void change(String a){
            a="yes";
        }
    }
    

    在这里插入图片描述

    展开全文
  • 主要介绍了JAVA参数传递方式,结合实例形式分析了java按值传递与引用传递区别及相关操作注意事项,需要的朋友可以参考下
  • 值传递与引用传递有哪些区别?

    千次阅读 2019-06-04 19:53:46
    Java语言提供了两种参数传递的方式:值传递引用传递 值传递   在方法调用中,实参会把它的值传递给形参,形参只是用实参的值初始化一个临时的存储单元。因此形参实参虽然有着响应的值,但是却有着不同的存储...

      方法调用是编程语言中非常重要的一个特性,在方法调用时,通常需要传递一些参数来完成特定的功能。Java语言提供了两种参数传递的方式:值传递和引用传递

    值传递
      在方法调用中,实参会把它的值传递给形参,形参只是用实参的值初始化一个临时的存储单元。因此形参与实参虽然有着响应的值,但是却有着不同的存储单元,因此对形参的改变不会影响实参的值。

    引用传递

      在方法调用中,传递的是是对象(也可以看作是对象的地址),这时候形参和实参的对象指的是同一块存储单元,因此对形参的修改就会影响实参的值。

      在Java语言中,原始数据类型在传递参数时都是按值传递,而包装类在传递参数时是按引用传递的。

    public class Test {
        public static void main(String[] args) {
            int i = 1;
            StringBuffer stringBuffer = new StringBuffer("Hello");
            testPassParameter(stringBuffer,i);
            System.out.println(stringBuffer);
            System.out.println(i);
        }
    
        private static void testPassParameter(StringBuffer s, int n) {
            s.append(" World");
            n = 8;
        }
    }
    

    在这里插入图片描述
    传递过程:
    在这里插入图片描述
    假设1和"Hello"的存储地址如图所示分别是0X12345678和0xFFFFFF12。在调用testPassParameter时,由于i为基本类型,因此参数是按值传递的,此时会创建一个i的副本,该副本与i具有相同的值,把这个副本作为参数赋值为n,作为传递的参数。
    而StringBuffer是一个类,因此是按照引用传递,传递的是它的引用也就是"Hello"的地址

    在testPassParameter内部修改的是n的值,这个值与i是没有关系的,但是在修改s时修改的是s这个地址指向的字符串,由于形参s和实参stringBuffer指向的是同一块存储空间,因此修改s后,s指向的字符串也被修改了。

    Java中处理8种基本的数据类型用的是值传递,其他所有类型都用的是引用传递

    public class Test {
        public static void main(String[] args) {
            Integer a = 1;
            Integer b = a;
            b++;
            System.out.println(a);
            System.out.println(b);
    
            StringBuffer s1 = new StringBuffer("Hello");
            StringBuffer s2 = new StringBuffer("Hello");
            changeStringBuffer(s1,s2);
            System.out.println(s1);
            System.out.println(s2);
        }
    
        private static void changeStringBuffer(StringBuffer ss1, StringBuffer ss2) {
            ss1.append(" World");
            ss2 = ss1;
        }
    }
    

    在这里插入图片描述

    对于前两个输出一个"1"和"2",有人可能会认为Integer是按值传递。但其实是引用传递,只是由于Integer是不可变类,因此没有提供改变它值的方法,在上例中,在执行完b++后由于Integer是不可变类,因此没有提供改变它值的方法,在上例中,在执行完b++后,由于Integer是不可变类,因此此时会创建一个新值为2的Integer赋值给b,此时b与a已经没有任何关系了。
    在这里插入图片描述
    为了便于理解假设s1和s2指向的字符串地址分别为0X12345678和OXFFFFFF12,并且在参数传递是是按引用传递也就是s1和s2的地址。在调用方法ss1.append(“World”)时,会修改ss1所指向的字符串的值,因此会修改s1的值,得到输出结果为Hello World。但是在执行ss2 = ss1时,只会修改ss2的值而对s2的值毫无影响,因此s2在调用前后保持不变。

    展开全文
  • js中的值传递与引用传递

    千次阅读 2018-12-03 16:25:34
    js一共有六大数据类型。number string boolean object null underfind 要说js的赋值方式时首先要说明js的... 基本类型存放在栈区,访问是按访问的,就是说你可以操作保存在变量中的实际的。 var a = 10; var ...

    js一共有六大数据类型。number string boolean object null underfind

    要说js的赋值方式时首先要说明js的数值类型:基本类型和引用类型。

    基本数据类型

    基本的数据类型有:undefined,boolean,number,string,null。 基本类型存放在栈区,访问是按值访问的,就是说你可以操作保存在变量中的实际的值。

    var a = 10;
    var b = a;
    a = 20;
    console.log(a);  //20
    console.log(b);  //10
    

    image.png

    结论:这种赋值类似于拷贝了一份。a和b在 var b = a;后就再也没有关系了。互不影响。

    引用赋值

    引用类型指的是对象:js中的array和object。可以拥有属性和方法,并且我们可以修改其属性和方法。引用对象存放的方式是:在栈中存放变量名(该变量的值是堆中真实数据的指针(对象在堆中的存放地址)),在堆中存放数据(真正的数据)。

    对象使用的是引用赋值。当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在堆中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
    image.png

    数组和对象赋值时的奇特现象

    var a = [1,2,3];

    var b = a;

    a = [4,5,6];

    alert(b); //[1,2,3]

    好像数组是基本类型一样。。,但是:

    var a = [1,2,3];

    var b = a;

    a.pop();

    alert(b); //[1,2]

    这是怎么回事?因为:(知乎解释)

    a = [4,5,6];//改变的是a引用本身,没有改变数组对象,a和b没有了关系。简单点:在堆中开辟了内存0xx2 存放[4,5,6],而后a的值变成了0xx2,而之前堆中0xx1依旧存储着[1,2,3],b的值是0xx1,所以b不收a的影响。
    a.pop();//改变的是数组对象,a引用没有改变。
    b = a;//该操作后,b直接指向数组对象,不是b指向a,a再指向数组。
    //所以改变a引用并不会对b引用造成影响,改变数组对象可以。

    作者:Intopass
    链接:https://www.zhihu.com/question/26042362/answer/31903017
    来源:知乎

    参数传递

    js的函数参数传递为值传递。

    当传入的是 基本类型的参数时:就是复制了份内容给i而已,i与age之间没有关系。

    function setAge(i)

    {
    alert(i);//24
    i = 18;
    alert(i);//18,i的改变不会影响外面的age
    };

    var age = 24;
    setAge(age);
    alert(age);//24
    当传入的参数为引用类型时:

    function setName(obj)

    {
    obj.name = ‘haha’;
    };

    var obj2 = new Object();
    setName(obj2);
    alert(obj2.name); // haha

    这看起来很像是传递的是引用,因为obj.name受到改变了,但其实不是,其实还是值,因为obj2本身的值就是新对象的地址,所以传进去的就是这个地址。

    这是阿里2014年的笔试题:

    var a = 1;

    var obj = {
    b: 2
    };
    var fn = function () {};
    fn.c = 3;

    function test(x, y, z) {
    x = 4;
    y.b = 5;
    z.c = 6;
    return z;
    }
    test(a, obj, fn);
    alert(a + obj.b + fn.c);
    答案:12

    首先test传递进去的实参中,a是基本类型(,复制了一份值),obj是object(指向地址,你动我也动),fn也当然不是基本类型啦。在执行test的时候,x被赋值为4(跟a没关系,各玩各的,a仍然为1),y的b被赋值为5,那obj的b也变为5,z的c变为6,那fn的c当然也会是6. 所以alert的结果应该是1+5+6 =12. (其实test不返回z也一样,z仍然改变的)。

    思考:那怎么保证一个对象调用一个js方法(js方法会改变其中数据),又想之后使用调用方法前的对象呢?

    var a = {name:1, value:2};
    var b = JSON.parse(JSON.stringify(a));
    b.name = 'mary';
    console.log(a);  //{name: 1, value: 2}
    console.log(b);  //{name: "mary", value: 2}
    

    感谢

    感谢原文作者:https://www.cnblogs.com/telnetzhang/p/5714920.html

    展开全文
  • 另一方面,值传递由于形参和实参内存地址不一样,有些功能并不能实现(swap()),因此,除了极为简单的函数会使用值传递外,大多数会采用引用传递。而对于指针传递,则在涉及数组的情况下使用较多,因为指针本身会给...
  • Java 是值传递还是引用传递

    万次阅读 多人点赞 2019-03-20 02:40:16
    最近整理面试题,整理到值传递引用传递,到网上搜了一圈,争议很大。带着一脸蒙圈,线上线下查了好多资料。最终有所收获,所以分享给大家,希望能对你有所帮助。 首先说下我的感受,这个题目出的很好,但是在 ...

        最近整理面试题,整理到值传递、引用传递,到网上搜了一圈,争议很大。带着一脸蒙圈,线上线下查了好多资料。最终有所收获,所以分享给大家,希望能对你有所帮助。
        首先说下我的感受,这个题目出的很好,但是在 Java 中这个题目是有问题的(在下面我会解释)。并且,有很多结论是 Java 中只有 值传递。我认为这样说不够严谨。当然如果针对 Java 语言本身来讲,Java 中只有 值传递,没有引用传递,是正确的。但是如果针对 值传递,引用传递定义来说,Java 中还是有引用传递的。下面来分析:

    一、值传递、引用传递定义


        在深入分析问题之前,先让初问者简单明白一下什么是值传递,引用传递。我先用 Java 代码解释:

    public class StringBase {
    
        public static void main(String[] args) {
            int c = 66; //c 叫做实参
            String d = "hello"; //d 叫做实参
    
            StringBase stringBase = new StringBase();
            stringBase.test5(c, d); // 此处 c 与 d 叫做实参
    
            System.out.println("c的值是:" + c + " --- d的值是:" + d);
        }
        
        public void test5(int a, String b) { // a 与 b 叫做形参
            a = 55;
            b = "no";
        }
    }


    【运行结果】
    c的值是:66 --- d的值是:hello

    可以看出通过方法传递后,int 类型与 String 类型的原值并没有受到前面 test5 方法执行后的影响,还是输出了原值。这种形为通常被说成值传递。如果原值经过 test5 方法后被改变了,这种形为通常被描述为引用传递

    定义

        值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
        引用传递:是指在调用函数时将实际参数的地址直接传递到函数中(的形参),那么在函数中对参数所进行的修改,将影响到实际参数。
        引用传递:形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。(下面文章中 C++ 的定义,我觉得这样说更精简形象一些,所以放了两个定义,其实意思是一样的)

        以上,就是相关的定义,大家对这个定义几乎没有分歧,但是我建议大家,有必要去看看 C++ 中 值传递、引用传递的定义。因为在 C++ 中有三个定义:值传递、引用传递、指针传递,推荐一个地址: C++ 值传递、指针传递、引用传递详解

    //引用传递
    void change2(int &n) {
        cout << "引用传递--函数操作地址" << &n << endl;
        n++;
    }

        我们看上边 C++ 引用传递的代码,使用的 & 操作符。& 操作符在 C++ 中被定义为"引用",引用在 C++ 中的定义是“引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样”,再看引用其中的一个描述:“声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元”。因此这引用的概念在 Java 中根本不存在。Java 中哪有给变量起个别名的!!!
        因此说,这个题出的就有问题,在 Java 官方中我一直没有找到明确的证据说“Java 中 值传递、引用传递 的定义”我所看到的全是说 C++ 中关于值传递、引用传递的定义。但是,在 Java 中没有 C++ 里"引用"的概念。Java 里只有对象,new 关键字。这就很尴尬了,拿 C++ 中的定义,来解释 Java,我觉得这就是有问题的。问题就出在了引用传递!!!
        在 C++ 中关于引用传递的定义明确,代码解释清晰。在 C++ 中引用传递,传递的是一个别名,操作别名就跟操作原值一个样。
        然而在 Java 中,没有引用的概念,Java 中只要定义变量就会开辟一个存储单元。因此,对 Java 语言来说只有值传递,没有引用传递是正确的。
        虽然 Java 中没有引用(C++ 中 引用"&")。但是,引用传递的定义,在 Java 中还是有符合条件的。抛开语言中的特性。只针对:值传递、引用传递的定义我们来分析一下,Java 是属于值传递还是引用传递。
        要想知道 Java 是属于值传递还是引用传递,这就要从 Java 内存模型聊起了,我们来看基本数据类型与引用类型在内存中的存储方式。

    二、基本数据类型、引用类型

    1.基本数据类型、引用类型定义
        基本数据类:Java 中有八种基本数据类型“byte、short、int、long、float、double、char、boolean”
        引用类型:new 创建的实体类、对象、及数组
    2.基本数据类型、引用类型在内存中的存储方式
        基本数据类型:存放在栈内存中。用完就消失。
        引用类型:在栈内存中存放引用堆内存的地址,在堆内存中存储类、对象、数组等。当没用引用指向堆内存中的类、对象、数组时,由 GC回收机制不定期自动清理。
    3.基本类型、引用类型内存简单说明图


        好,看了基本的内存图,应该能明白 Java 是属于值传递还是引用传递。不明白,也没关系,下面会详细说明,先说引起争议的代码。

    三、在 Java 中 值传递 与 引用传递,产生模糊不清的代码

    public class TransmitTest {
    
        public static void main(String[] args) {
    
            String a = "hello"; //String 引用数据类型,调用 pass 方法后 b 的值没有改变,不是 hello
            int b = 1; //int 基本数据类型,调用 pass 方法后 a 的值没有改变,还是 1
    
            User user = new User(); //new Class 引用类型,调用 pass 方法后 name 与 age 的值改变了
            user.setName("main"); // 调用 pass 后,name 为 pass 了
            user.setAge(2); //调用 pass 后,age 为 4 了
    
            pass(user, a, b); //pass 方法调用
    
            System.out.println("main 方法 user 是:" + user.toString());
            System.out.println("main 方法 a 的值是:" + a + " --- b 的值是:" + b);
        }
    
        public static void pass(User user, String a, int b) {
    
            a = "你好";
            b = 3;
    
            user.setName("pass");
            user.setAge(4);
    
            System.out.println("pass 方法 user 是:" + user.toString());
            System.out.println("pass 方法 a 的值是:" + a + " --- b 的值是:" + b);
        }
    }
    
    class User {
    
        String name;
        int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "name = " + name + " --- age = " + age;
        }
    }

    【运行结果】
    pass 方法 user 是:name = pass --- age = 4
    pass 方法 a 的值是:你好 --- b 的值是:3
    main 方法 user 是:name = pass --- age = 4
     

        main 方法 a 的值是:hello --- b 的值是:1    结果分析,int b,实参是 1,pass 方法调用后,值还是 1 没变,说明基本数据类型是值传递,大家对这个也几乎没争议。
    争议的在下边了:
            1.String a 是引用类型,pass 方法调用后,值还是 hello 没变。(结论:好像引用类型也是值传递啊!!!)
            2.new User() 也是引用类型,在方法调用后,值居然变了。原值不应该是 name = main,age = 2 的吗?为什么 name = pass,age = 4 了呢?(结论:引用类型好像是引用传递啊???)
        这就奇葩了,String 与 new 创建的类,同为引用类型,为什么产生的结果不一样呢?String 不也是一个类吗?User 不也是一个类吗?
        有人解释说这个代码比喻的不对,应该用如下代码比喻,在 pass 方法中添加一行代码,user = new User(),pass 方法修改如下:

    public static void pass(User user, String a, int b) {
    
        a = "你好";
        b = 3;
    
        user = new User();
        user.setName("pass");
        user.setAge(4);
    
        System.out.println("pass 方法 user 是:" + user.toString());
        System.out.println("pass 方法 a 的值是:" + a + " --- b 的值是:" + b);
    }


    【运行结果】
    pass 方法 user 是:name = pass --- age = 4
    pass 方法 a 的值是:你好 --- b 的值是:3
    main 方法 user 是:name = main --- age = 2
    main 方法 a 的值是:hello --- b 的值是:1

        这样一来,改变了形参的值,但是实参没有改变。因此有人得出结论,Java 中只有值传递,没有引用传递。(我并不这么认为,原因如下)
        使用 user = new User() 这个代码来做验证,我觉得是符合 String 类型做形参时的验证地,但是,此示例不符合引用传递的验证
        在验证之前,我们先看下使用 user=new User(); 语句之前与之后的内存模型图,能有助于我们更好的验证结果,同时也有助于更好的理解 Java 内存模型。我们看 TransmitTest 类在 Java 内存模型中的存储图:

    图1 pass() 方法中没有使用 user=new User() 语句的内存模型图


        在 图1 中,main() 方法中的 user 类,与 pass() 方法中的 user 类,指向的是同一个堆内存中的 User 类,红色虚线是在 main() 方法中初次给 name 属性赋的值"main"。实线部分,是在 pass() 方法中给 name 属性赋的值"pass"。因为在堆内存中只有一个 User 类实体,因此 main() 方法与 pass() 方法中的 user 指向的都是同一个 User 类 0x000031。因此,无论在 main() 方法还是 pass() 方法中,改变其 user 的属性值后,打印 User 类的属性值肯定是一样的,他们用的是一个实体类。

    图2 pass() 方法中使用了 user=new User() 语句的内存模型图


        在 图2 中,main() 方法中的 user 类首次加载,堆内存开辟了一个地址为 0x000031 的 User 类实体。当把 main() 方法中的实参 user 传递给 pass() 方法中形参 user 的时候,栈内存在 pass() 方法区中开辟了一个空间,并引用了地址为 0x000031 的 User 类。此时两个方法中的 User 类其实是一个。
        然而当 pass() 方法中的 user=new User()语句执行后,堆内存中新开辟了一个地址为 0x000032 的 User 类,pass() 方法中的 user 从此指向了地址为 0x000032 的 User 类。
        因为 pass() 方法 与 main() 方法中的 user 属性分别指向了不同的 User 类,所以两个方法中的 User 类的属性无论怎么修改,相互都不影响。
        但是,这种操作是不能验证引用传递定义的。因为实参传值给形参后,形参自己改变了地址,这就和引用传递无关了。我们再来用代码验证。
        我们可以使用 C++ 引用传递代码来验证,使用 user = new User() 语句验证引用传递的错误性
    C++ 中引用传递代码

    class User
    {
    public:
        int age;   // 长度
        string name;  // 宽度
    };
    
    
    //引用传递
    void pass(User &user) {
    
        cout << "引用传递 -- user的地址是:" << &user << endl;
    
        user.age = 2;
        user.name = "你好";
    }
    
    
    int main() {
    
        User user;
        user.age = 1;
        user.name = "hello";
    
        cout << "实参 -- user的地址是:" << &user << endl;
        pass(user);
        cout << "实参 -- user的值 age=" << user.age << ",name=" << user.name << endl;
    
        system("pause");
        return false;
    }


    【运行结果】
    实参 -- user的地址是:00DCF768
    引用传递 -- user的地址是:00DCF768
    实参 -- user的值 age=2,name=你好

        在 C++ 中,引用传递的实参与形参地址一致,在引用的方法中,使用的就是实参的地址。当修改形参值后,实参值也跟着变。现在我们按照 user=new User(); 的方法改变一下引用方法 pass 如下:

    //引用传递
    void pass(User &user) {
    
        cout << "引用传递 -- user的地址是:" << &user << endl;
    
        User user2 = user; //相当于 Java 中的 user=new User();
        cout << "引用传递 -- user2的地址是:" << &user2 << endl;
    
        user2.age = 2;
        user2.name = "你好";
    }


    【运行结果】
    实参 -- user的地址是:00CFFACC
    引用传递 -- user的地址是:00CFFACC
    引用传递 -- user2的地址是:00CFF9AC
    实参 -- user的值 age=1,name=hello

        我们看,改变引用传递中形参 user 的地址后(后期改变的地址,这跟引用传递,值传递还有什么关系?),再修改形参 user 的值,实参没有任何变化。这就破坏了引用传递的场景,因此不能使用 user=new User(); 语句来验证引用传递的定义。

        排除了其他异议,我们再来分析 Java 中有没有引用传递。

    先把引用传递的定义放上

        引用传递:是指在调用函数时将实际参数的地址直接传递到函数中(的形参),那么在函数中对参数所进行的修改,将影响到实际参数。
        引用传递:形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。

        经过上面的长篇大论,我想这时候你应该能明白了。在对引用类型做方法传递的时候,是不是先把实参的地址给形参的?之后对形参的操作是,是不是相当于操作实参?最后有没有影响到实际参数?
    答案肯定都是有的。

    定义关键1:是指在调用函数时将实际参数的地址直接传递到函数中(给形参了)
        证明:Java 在进行方法调用传递引用类型参数的时候,就是先给形参一个与实参相同的地址的(此处与 C++ 的不同之处是,C++ 是别名,没有在内存中给形参开辟空间,而 Java 给形参开辟了一个栈内存空间,存放与实参相同的引用地址。但是这与引用传递的定义不违背啊!!!定义可没说形参是否有开辟空间的概念)。

    定义关键2:在函数中对参数所进行的修改,将影响到实际参数。
        证明:Java 在进行方法调用传递引用类型参数后,修改形参的内容后,就是影响了实参的值。

    四、String 与包装类的特殊分析

        好了,解决了实例对象,我们再来说 String 与包装类,为什么 String 与包装类作为引用类型,却有值传递的功能,居然没有影响到实参!

    原因如下
        我们都知道。String 类型及其他七个包装类,是一群特殊群体。当使用 String a = "hello"; 语句时,相当于执行了 String a = new String("hello")。然而在 Java 中每一次 new 都是一次对象的创建。如果你创建的对象在堆中不存在,便会创建一个,如果是新创建的对象,那么地址都会变的,后期改变的地址,这跟引用传递,值传递还有什么关系?

        其实 String 型方法参数传值的过程,可以用以下代码来解释,我们先看 String 类型的还原:

    String a = "hello"; //a 相当于实参
    String a1 = a; //a1 就相当于形参
    a1 = "你好";
    System.out.println("a是:" + a + " --- a1是:" + a1);


    【运行结果】
    a是:hello --- a1是:你好

    逐步还原解释:
        String a = "hello"; 在 String 池中检查并创建一个常量:"hello",给 a 分配一个栈内存,在此存储常量 hello 的地址。
        String a1 = a; 给 a1 分配一个栈内存,在此存储常量 hello 的地址。相当于 a 把自己持有的地址,复制给了 a1。

    内存图如下


        a1 = "你好"; 等同于 a1 = new String("你好")。在 String 池中检查是否有 "你好" 的常量。如果有,将 a1 的地址指向 "你好" 的地址。如果 String 池中没有 "你好" 常量,在堆内存中创建 "你好" 常量,并将 a1 地址指向 "你好"。

    内存图如下


        总结如下:String 类型,在进行方法传参的时候,是先将实参地址,赋值给形参(形参在栈内存中确实新开辟了一个新的内存空间,用于存储地址)。但是当再次给 String 类型的形参赋值(与实参内容不一样的值时),形参地址变了,这就和引用传递无关了。我们可以用 C++ 代码中的引用传递,来验证 String 型的这一特殊情况,代码如下:

    //引用传递
    void pass(string &a, int &b) {
    
        cout << "引用传递 -- a的地址是:" << &a << " --- b的地址是:" << &b << endl;
        cout << "引用传递 -- a的值是:" << a << " --- b的值是:" << b << endl;
    
        string c = a; // 相当于 java 中的 new String
        int e = b;
    
        cout << "引用传递 -- c的地址是:" << &c << " --- e的地址是:" << &e << endl;
        cout << "引用传递 -- c的值是:" << c << " --- e的值是:" << e << endl;
    
        c = "你好"; //在引用传递中改变形参地址后做修改操作,不影响实参
        e = 2; //在引用传递中改变形参地址后做修改操作,不影响实参
    }
    
    int main() {
        string a = "hello";
        int b = 1;
    
        cout << "实参 -- a的地址是:" << &a << " --- b的地址是:" << &b << endl;
    
        pass(a, b);
    
        cout << "实参 -- a的值是:" << a << " --- b的值是:" << b << endl;
    
        system("pause");
        return false;
    }


    【运行结果】
    实参 -- a的地址是:00CFF9CC --- b的地址是:00CFF9C0
    引用传递 -- a的地址是:00CFF9CC --- b的地址是:00CFF9C0
    引用传递 -- a的值是:hello --- b的值是:1
    引用传递 -- c的地址是:00CFF8A0 --- e的地址是:00CFF894
    引用传递 -- c的值是:hello --- e的值是:1
    实参 -- a的值是:hello --- b的值是:1

        我们看,在 C++ 中的引用传递方法中,改变形参的地址后做修改操作,照样不影响实参的值,这就破坏了引用传递的本质,不能这样比喻。

        因此,String 与其他包装类,在做形参的时候,由于他们在赋不同于实参的值时,改变了形参的地址,因此使引用传递,看起来像值传递,其实本质还是引用传递。


    五、总结


    1.这个题目出的不严谨,但是很好(因为涉及了 Java 内存模型)
    2.就 Java 语言本身来说,只有值传递,没有引用传递。
    3.根据 值传递,引用传递的定义来说:
            Java 中的基本类型,属于值传递。
            Java 中的引用类型,属于引用传递。
            Java 中的 String 及包装类,属于特殊群体,作为形参时,由于每次赋值都相当于重新创建了对象,因此看起来像值传递,但是其特性已经破坏了,值传递、引用传递的定义。因此他们属于引用传递的定义,却表现为值传递。

    此题争议很大,我仅分享自己的理解,如有不同结论,欢迎指正,一起共勉!

    展开全文
  • JAVA参数传递方式 (按值传递与引用传递区别)

    千次阅读 多人点赞 2018-09-30 22:58:30
    首先要明确的是JAVA中没有引用传递, 全部是按调用 令大家所费解的 当对象引用作为参数时 函数为什么能修改真实的对象呢?这不是引用传递的特征吗? 尤其先学习C++再学习JAVA的同学(比如说我自己)会这样认为, 用...
  • 值传递与引用传递

    万次阅读 2017-10-23 10:28:14
    char ch[] 是引用传递,修改了原内容。 永远记得,数组和对象都是引用传递。 call by value不会改变实际参数的数值 call by reference不能改变实际参数的参考地址 call by reference能改变实际参数的内容
  • go语言中的值传递与引用传递,通过此篇文章让你一目了然。
  • 一、值传递与引用传递的区别 ? 值传递 值传递的时候,将实参的值,copy一份给形参。 引用传递 引用传递的时候,将实参的地址值,copy一份给形参。 也就是说,不管是值传递还是引用传递,形参拿到的仅仅是实参...
  • 主要介绍了java到底是值传递还是引用传递的相关知识,本文通过几个例子给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • ABAP 值传递与引用传递

    千次阅读 2019-04-18 15:27:41
    1. Call By Reference(引用传递): 传参数时将资料的存放地址(address)传至参数中, 也就是子程序中的参数变量外部实际变量共享地址内的, 又称为 Call By Address, 如果在子程序中地址中的改变了, 外部实际...
  • java值传递引用传递(附实例)

    千次阅读 2019-12-16 22:46:05
    java值传递引用传递1.数据类型1.1 基本数据类型1.2 引用数据类型2.形参实参 观前提示: 本文所使用的IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141。 1.数据类型 1.1 基本数据类型 基本数据类型包括数值型...
  • Go语言中函数的参数都是按值进行传递的,即使参数是指针,也是指针的...Golang数组作为参数传入函数时,进行的是值传递,这里Java数组的引用传递是不同的,示例如下 package main import "fmt" func main() { ar.
  • java值传递与引用传递

    2012-12-24 11:17:41
    不管是按值传递还是按引用传递,都是把栈中的数据备份了一份给参数变量,只不过值类型备份的是具体的数值,而引用类型备份的是内存地址
  • 主要介绍了深入理解python中函数传递参数是值传递还是引用传递,涉及具体代码示例,具有一定参考价值,需要的朋友可以了解下。
  • 主要介绍了 Java 值传递引用传递详解及实例代码的相关资料,需要的朋友可以参考下
  • 主要介绍了详解java的值传递、地址传递、引用传递的相关资料,需要的朋友可以参考下
  • 值传递引用传递的区别

    千次阅读 2018-07-19 21:13:00
    值传递是指基本数据类型在方法中的传递,引用传递是指引用数据类型在方法中的传递,举例来说,如下图程序代码运行所示: 注:int属于基本数据类型,因此在方法中进行传递和引用时,并不会改变该变量的数值 而arr...
  • Java中的参数传递,到底是值传递还是引用传递? 错误理解一:值传递引用传递,区分的条件是传递的内容,如果是个值,就是值传递。如果是个引用,就是引用传递。 错误理解二:Java是引用传递。 错误理解三:传递的...
  • java中的值传递引用传递的区别?

    千次阅读 2018-11-29 21:04:51
    1.值传递概念:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 实例: public class Main { public static void main(String[] args) { int ...
  • 基于方法参数的传递有两种方式:值传递引用传递值传递表示方法接收的是调用者提供的值。 引用传递表示方法接收的是调用者提供的变量地址。 Java程序设计语言总是采用按值传递的方式,也就是说,方法得到的...
  • 面试遇到这题,回答的是值传递,回头在网上查看,各种说法都有,我都晕了,大神详细介绍下值传递与引用传递吧!
  • "撩妹"},20,true} yangge.Love() //要求传递值就必须传递值 //要求传递指针就必须传递指针 MakeHimLove(yangge) MakeHisPtrLove(&yangge) //值传递的是副本,引用传递传递的才是真身 for i:=0;i;i++{ ...
  • java基本数据类型传递与引用传递区别详解

    万次阅读 多人点赞 2016-04-19 17:12:57
    java的值传递引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题,首先我们必须认识到这个问题一般是相对函数而言的,也就是java中的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给...
  • C++值传递引用传递的区别

    千次阅读 2020-05-27 17:16:02
    c++中参数传递的区别: 1.值传递: 可以想象改变的只是实参的“替身”的值,而实参本身不会被改变。...2.引用传递 可以想象成是“同一个人”,只不过把名字换了换,但本质上还是同样的。 因此,引用并不分配独
  • 主要介绍了JS是按值传递还是按引用传递(推荐)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • 深入理解--Java按值传递和按引用传递

    万次阅读 多人点赞 2017-07-20 15:48:49
    引言最近刷牛客网上的题目时碰到不少有关Java按值传递和按引用传递的问题,这种题目就是坑呀,在做错了n次之后,查找了多方资料进行总结既可以让自己在总结中得到提高,又可以让其他人少走弯路。何乐而不为?Java按...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 675,013
精华内容 270,005
关键字:

值传递与引用传递

友情链接: AN10866.zip