[原创]Java基础巩固篇之值传递和引用传递详解_Tomcat, WebLogic及J2EE讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Tomcat, WebLogic及J2EE讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2247 | 回复: 0   主题: [原创]Java基础巩固篇之值传递和引用传递详解        下一篇 
ming.chen
注册用户
等级:中尉
经验:444
发帖:8
精华:0
注册:1970-1-1
状态:离线
发送短消息息给ming.chen 加好友    发送短消息息给ming.chen 发消息
发表于: IP:您无权察看 2016-5-10 18:51:53 | [全部帖] [楼主帖] 楼主

    前段时间写java代码遇到一个值传递和引用传递的问题,回去查了下相关资料,对Java参数传递问题有了新的理解和认识,但是有个问题还是很困惑,那就是Java里到底是不是只有值传递,因为查阅资料的过程中,看到很多大牛说Java只有值传递,引用传递其实传递的是地址值,本身来说也是一种值传递,但是也有人说既有值传递,又有引用传递,姑且不去争论这个究竟,只是站在不同角度看待同一个问题所以得出了两个不同的观点,其实两个说法的原理是一样的,只要搞清楚Java参数传递的机制,叫什么传递也无所谓了,接下来跟大家分享一下我的一些粗浅的心得:

    1.什么是值传递

        传递实参的一个副本给形参,在被调用函数内对形参的修改不会影响到原来的实参。  

    public class Test {
    
    public static void main(String[] args) {
        int a=1;
        Test.changeNum(a);
        System.out.println("Main方法中的a = "+a);
    }
    public static void changeNum(int a){
        //do something
        a+=1;
        System.out.println("changeNum方法中的a = "+a);
    }
}

运行结果是:

changeNum方法中的a = 2
Main方法中的a = 1

    可见实际参数的值并没有发生改变,改变的只是作为副本的形参。

     值传递重要特点:传递的是值的拷贝,传递后就没有任何联系了。


    2.什么是引用传递

        本质上还是值传递,只是把引用的值复制一份传递给形参,指向实参引用所指向的值,当对形参指向的内容操作时,就相当于对实参本身就行的操作。     

public class Test1 {

    public static void main(String[] args) {
        A a = new A();
        a.age=10;
        test1(a);
        System.out.println("Main方法里age = "+a.age);
    }
    public static void test1(A a){
        a.age=20;
        System.out.println("test1方法里age = "+a.age);
    }
}
class A{
    int age=0;
}

运行结果如下:

test1方法里age = 20
Main方法里age = 20

 3. 引用传递的过程-内存分配示意图

    要想正确的理解java的引用传递,就必须了解java内存分配的过程,下面的内存分配示意图可以帮助我们理解这个过程:

    (1)运行开始,到第4行,Main方法里创建了一个类A的实例,内存分配示意图如下:

            main方法里的变量age→这是类A的一个实例a,此时age=0.

    (2)运行到5行,是修改A实例里age的值,运行后内存分配示意图如下:

            main方法里的变量age→这是类A的一个实例a,此时age=10.

    (3)运行到6行,是把main方法中的变量a所指向的内存空间地址,按引用传递给test1方法中的a变量。*注意:这两个变量a是完全不同的,不要被名称相同所蒙蔽。内存分配示意图如下:

            QQ图片20160510182603.png

    由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图:

            QQ图片20160510182946.png

    (4)运行到10行,为test1方法里的变量a指向的A实例的age进行赋值,然后形成新的内存示意图:

            QQ图片20160510183144.png

            此时A实例的age值的改变是由test1方法的形参改变引起的。

    (5)运行到11行,输出test1方法里的age=20.

    (6)运行到第7行,输出Main方法里的age=20.


    4. 再次理解引用传递

        将上述代码稍作修改:

    public class Test1 {

    public static void main(String[] args) {
        A a = new A();
        a.age=10;
        test1(a);
        System.out.println("Main方法里age = "+a.age);
    }
    public static void test1(A a){
        //此处增加了一行,将形式参数指向了一个新的A的实例
        a=new A();
        a.age=20;
        System.out.println("test1方法里age = "+a.age);
    }
}
class A{
    int age=0;
}

运行结果:

里age = 20
Main方法里age = 10

其实也不难理解,前面3部和上述相同,第4步开始如下:

(4)运行到11行,作为形参的a变量指向了新的A的实例。

    QQ图片20160510184052.png

(5)运行到12行,形参a变量的age重新赋值

    QQ图片20160510184418.png

    此时修改的是test1方法变量a的age,与main方法中的变量a所指的地址不同,所以main方法中的变量a的age值没有发生改变。

(6)运行到13行,输出test1方法里的age =20.

(7)运行到7行,输出Main方法里的age=10.


5.引用传递String类型的探讨

    我们都知道java里的String类型是一种引用类型,而不是值类型,虽然很多地方和值类型的特征相似,看下面这个例子:

public class Test {
    
    public static void main(String[] args) {
        String str="Hello";
        Test.changeStr(str);
        System.out.println("Main方法中的str = "+str);
    }
    public static void changeStr(String str){
        //do something
        str+=" World!";
        System.out.println("changeStr方法中的str = "+str);
    }
}

输出结果:

changeStr方法中的str = Hello World!
Main方法中的str = Hello

那么为什么String类型的引用传递没有改变Main方法里的str的值呢?大家可以去深入了解下java里String类型的特性,答案就显而易见,这里就不做赘述了。以上是我的一点浅薄的见解,希望大家多多指教。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论