zoukankan      html  css  js  c++  java
  • Java方法中传值和引用传递的问题(转)

    说明:标题其实说法是错误的。Java中只有值传递,没有引用传递。

    ... ...  
    //定义了一个改变参数值的函数  
    public static void changeValue(int x) {  
        x = x *2;  
    }  
    ... ...  
    //调用该函数  
    int num = 5;  
    System.out.println(num);  
    changeValue(num);  
    System.out.println(num);  
    ... ...  

    调用函数changeValue()前后num的值都没有改变。

    值传递的过程:

    num作为参数传递给changeValue()方法时,是将内存空间中num所指向的那个存储单元中存放的值,即"5",传送给了changeValue()方法中的x变量,而这个x变量也在内存空间中分配了一个存储单元,这个时候,就把num的值5传送给了这个存储单元中。此后,在changeValue()方法中对x的一切操作都是针对x所指向的这个存储单元,与num所指向的那个存储单元没有关系!

    自然,在函数调用之后,num所指向的存储单元的值还是没有发生变化,这就是所谓的“值传递”!值传递的精髓是:传递的是存储单元中的内容,而非地址或者引用!

    ... ...  
    class person {  
    public static String name = "Jack";  
        ... ...  
    }  
    ... ...  
    //定义一个改变对象属性的方法  
    public static void changeName(Person p) {  
        p.name = "Rose";  
    }  
    ... ...  
    public static void main(String[] args) {  
        //定义一个Person对象,person是这个对象的引用  
        Person person = new Person();  
        //先显示这个对象的name属性  
        System.out.println(person.name);  
        //调用changeName(Person p)方法  
        changeName(person);  
        //再显示这个对象的name属性,看是否发生了变化  
        System.out.println(person.name);  
    }  

    第一次显示:“Jack”

    第二次显示:“Rose”

    方法用了一个对象参数,该对象内部的内容就可以改变,之前一直认为应该是该对象复制了一个引用副本给调用函数的参数,使得该方法可以对这个对象进行操作,其实是错了!

    Java编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。  

    为什么这里是“值传递”,而不是“引用传递”?

    主函数中new了一个对象Person,实际分配了两个对象:新创建的Person类的实体对象,和指向该对象的引用变量person。

    注意:在Java中,新创建的实体对象在堆内存中开辟空间,而引用变量在栈内存中开辟空间

    正如如上图所示,左侧是堆空间,用来分配内存给新创建的实体对象,红色框是新建的Person类的实体对象,000012是该实体对象的起始地址;而右侧是栈空间,用来给引用变量和一些临时变量分配内存,新实体对象的引用person就在其中,可以看到它的存储单元的内容是000012,记录的正是新建Person类实体对象的起始地址,也就是说它指向该实体对象。

    调用了changeName()方法,person作为对象参数传入该方法,person引用变量将自己的存储单元的内容传给了changeName()方法的p变量!也就是将实体对象的地址传给了p变量,从此,在changeName()方法中对p的一切操作都是针对p所指向的这个存储单元,与person引用变量所指向的那个存储单元再没有关系!

    p所指向的那个存储单元中的内容是实体对象的地址,使得p也指向了该实体对象,所以才能改变对象内部的属性!

    示例参考:

    package com.jsoft.testjavabasics.test1;
    
    /**
     * This is Description
     *
     * @author jim
     * @date 2017/11/25
     */
    public class TestClass {
    
        private void add(int i, int j) {
            i += 1;
            j += 1;
        }
    
        private void add(Integer a, Integer b) {
            a += 1;
            b += 1;
        }
    
        private int add(int i) {
            return ++i;
        }
    
        private Integer add(Integer a) {
            return ++a;
        }
    
        private void add(Integer[] integers) {
            integers[0] = 2;
            integers[1] = 2;
        }
    
        public void run() {
    
            int i = 1;
            int j = 1;
    
            add(i, j);
    
            System.out.println("add method:i:" + i + " j:" + j);
            // out:add method:i:1 j:1
    
            Integer a = 1;
            Integer b = 1;
    
            add(a, b);
    
            System.out.println("add method:a:" + a + " b:" + b);
            // out:add method:a:1 b:1
    
            i = add(i);
    
            System.out.println("add method:i:" + i);
            // out:add method:i:2
    
            a = add(a);
    
            System.out.println("add method:a:" + a);
            // out:add method:a:2
    
    
            Integer[] integers = new Integer[2];
            integers[0] = 1;
            integers[1] = 1;
            add(integers);
    
            System.out.println("add method:integers[0]:" + integers[0] + " integers[1]:" + integers[1]);
            // out:add method:integers[0]:2 integers[1]:2
    
        }
    }

    示例工程:https://github.com/easonjim/5_java_example/tree/master/javabasicstest/test30/test1

    参考:

    http://lyy3323.iteye.com/blog/609068

    http://ask.csdn.net/questions/206076

    http://bbs.csdn.net/topics/391065642?page=1

    http://guhanjie.iteye.com/blog/1683637(以上内容转自此篇文章)

    http://bbs.csdn.net/topics/390900983?page=1

  • 相关阅读:
    JavaScript对原始数据类型的拆装箱操作
    Javascript继承(原始写法,非es6 class)
    动态作用域与词法作用域
    自行车的保养
    探索JS引擎工作原理 (转)
    C语言提高 (7) 第七天 回调函数 预处理函数DEBUG 动态链接库
    C语言提高 (6) 第六天 文件(续) 链表的操作
    C语言提高 (5) 第五天 结构体,结构体对齐 文件
    C语言提高 (4) 第四天 数组与数组作为参数时的数组指针
    C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间
  • 原文地址:https://www.cnblogs.com/EasonJim/p/7896337.html
Copyright © 2011-2022 走看看