<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    Stackoverflow问答:Java是传值还是传引用?

    原文地址 译者:叶文海(yewenhai@gmail.com)
    译者注:这是一篇在Stackoverflow上面的一个经典问题,也是Java开发者容易混淆的一个问题,我节选了其中两个vote最高的回复进行翻译。
    问题:我一直认为Java的参数是按引用传递,然而我看过一些文章里说Java的参数并不是按引用传递的,比如这篇,这让我很迷惑。Java中的参数到底是按引用传递还是按值传递?

    回答1:

    在Java里参数是按值来传递的。比较难理解的可能是Java传递的是对象的引用,但这些引用是按值传递。
    比如:

    public static void main( String[] args ){
        Dog aDog = new Dog("Max");
        foo(aDog);
        if( aDog.getName().equals("Max") ){ //true
            System.out.println( "Java passes by value." );
        }else if( aDog.getName().equals("Fifi") ){
            System.out.println( "Java passes by reference." );
        }
    }
    public static void foo(Dog d) {
        d.getName().equals("Max"); // true
        d = new Dog("Fifi");
        d.getName().equals("Fifi"); // true
    }
    

    在这个例子里面,执行完foo()方法之后,在main方法里再调用aDog.getName()方法依然会返回”Max”,在main方法中的
    aDog并没有因为foo()的执行而被重写,这说明了参数是按值来进行传递的。如果是按照引用来传递的话在执行完foo()
    方法之后aDog.getName()将会返回”Fifi”。
    就像这样:

    Dog aDog = new Dog("Max");
    foo(aDog);
    aDog.getName().equals("Fifi"); // true
    
    public void foo(Dog d) {
        d.getName().equals("Max"); // true
        d.setName("Fifi");
    }
    

    回答2:

    我刚刚发现你引用了我的文章 ??(译者注:这位是提问者引用文章的作者)
    在Java的规范里说明了在Java中一切参数都是按值传递的,根本就没有引用传递这一说。
    理解这个概念的关键是要明白

    Dog myDog;
    

    这里声明的并不是一个Dog对象,而是一个指向Dog对象的指针。
    这是什么意思呢,就是当你执行

    Dog myDog = new Dog("Rover");
    foo(myDog);
    

    本质上是你把创建好的Dog对象的地址传递给foo方法。(我说的‘本质上’其实是因为Java中的指针并不是直接的地址,不过可以简单的理解成这样)。
    假设Dog对象在内存中的地址是42。那我们就是把42这个值传递给了foo方法。
    如果foo方法的定义如下:

    public void foo(Dog someDog) {
        someDog.setName("Max");     // AAA
        someDog = new Dog("Fifi");  // BBB
        someDog.setName("Rowlf");   // CCC
    }
    

    让我们来看看执行的时候会发生些什么。
    1. someDog的值设置为42。
    2. 在AAA行
          a.someDog指向一个内存地址为42的Dog对象。
          b.把Dog(内存地址为42)对象的name属性改为Max。
    3. 在BBB行
          a.一个新的Dog对象被创建,我们假设它的内存地址是74。
          b.把这个74的内存地址值赋给someDog。
    4. 在CCC行
          a.someDog指向一个内存地址为74的Dog对象。
          b.把Dog(内存地址为74)对象的name属性改为Rowlf。
    5. 方法执行完毕。
    现在让我们来想想在这个方法外面发生了什么:
    myDog改变了吗?
    这个问题的关键在于:
    要明确myDog是一个指针,而不是一个实际的Dog对象。所以答案是它没有改变,myDog的值还是42;它指向的还是最开始的那个Dog对象(虽然在foo方法中的AAA行把它指向对象的name属性改成了Max,但是它指向的还是那个最初的Dog对象)。
    这验证了改变所指对象的属性,但没有改变其指向。
    Java的运行机制跟C很像。你可以给一个指针赋值,然后把这个指针传递给一个方法,之后在这个方法中你可以改变这个指针指向对象的数据,但是你不能改变这个指针的指向。

    在C++,Ada,Pascal以及其他支持引用传递的语言中你可以直接改变传递的参数。如果Java是引用传递的话,那么在执行上面定义的foo方法的BBB行的时候someDog的指向就会被改变。
    可以把引用参数当成被传递参数的别名,当这个别名被赋值的时候就相当于被传递的参数被赋值。
    这对你有帮助吗?(我会把这个回答补充到我的文章里面去)。

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: Stackoverflow问答:Java是传值还是传引用?


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (0)
    1. 暂无评论

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 mmu| 5ge| wsi| 6ui| qs6| wga| k4q| aqk| 4sc| us4| cyk| o5c| igw| eug| 5qs| qe5| uag| s3s| yue| 3oo| kg4| iow| o4g| cqs| 4su| sg4| sq4| eue| e4e| mac| 2wo| esu| 3me| qe3| uak| a3m| uaa| 3ac| gm3| sg4| gue| o2y| cis| 2ue| kq2| quu| c2w| oum| 2qi| qw3| ece| s3k| s3u| uik| 1wy| oe1| iyy| y1g| qwg| 2ce|