日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

到底是傳值還是傳引用?

系統(tǒng) 1992 0

發(fā)現(xiàn)關(guān)于java中值傳遞還是引用傳遞,一些誤解挺多的,我的觀點(其實也不是我的觀點,咱都是二手販子)就是java中只有值傳遞;來吧,咱從頭來捋一下,本山大叔在賣拐里不是說了嘛,亂了咱就捋,從頭捋一下。

1. 啥叫值傳遞,啥叫引用傳遞。

在編譯原理中,我們會看到參數(shù)的傳遞有四種,定義如下:

Pass by value : This is the? mechanism supported by C . Value of parameters are copied into called routine.

Pass by reference : No copying is done, but a reference (usually implemented as a pointer) is given to the value. In addition to allowing the called routine to change the

values, it is also efficient means for passing large variables (such as structs ).

Pass by value-result : This interesting variant supported by languages such as Ada copies the value of the parameter into the routine, and then copies the (potentially changed)

value back out. This has an effect similar to pass-by-reference, but not exactly.

Pass by name : This rather unusual mechanism acts somewhat like C preprocessor macros and was introduced in Algol . Rather than evaluating the parameter value, the name or expression is actually substituted into the calling sequence and each? access to the parameter in the calling body re- evaulates it.

?

由定義可知:并不是我們傳遞某個參數(shù)時,若這個參數(shù)是某對象的引用,所以這就是引用傳遞,引用傳遞在程序設(shè)計領(lǐng)域有其自己的意義。

2. 參數(shù)傳遞是通過值傳遞,不是通過引用傳遞。

其實很多書籍都講到這一點,如 practical java 第一條講的就是它。 我們有時候會聽到說某方法傳遞了一個引用,其實應(yīng)該說準(zhǔn)確點,傳遞的是一個引用(型變量)-pass object reference by value,其傳遞的內(nèi)容依然是這個引用型變量的值,即:還是值傳遞。對象都是通過其對象變量來標(biāo)識的,而這個對象變量的值并不是對象本身,僅僅是存儲在另外一處的該對象的引用。網(wǎng)上很多文章會講到:這是不對的。

混淆值傳遞和引用傳遞通常會有個負(fù)面作用:一般認(rèn)為引用傳遞的結(jié)論還會加上一條-對引用的改變會影響原有變量的值--當(dāng)然,我們認(rèn)為這是錯誤的。

?? ? ? ? 看下面的代碼:

    import java.util.ArrayList;
import java.util.List;

public class ByValue {
    public static void main(String args[]) {

        // 1.pass primitive type parameter.
        int i = 0;
        System.out.println("initially the i is " + i);
        byPrimitive(i);
        System.out.println("now the i is " + i);

        // 2. pass reference type parameter and change the parameter's initial value.
        List<String> strList = new ArrayList<String>();
        strList.add("hello world");
        System.out.println("initially the strList is" + strList.toString());
        refType(strList);
        System.out.println("now the strList is" + strList.toString());

        // 3.pass reference type parameter and remain the parameter's initial value .
        List<String> strList2 = new ArrayList<String>();
        strList2.add("hello world ");
        System.out.println("initially the strList2 is" + strList2.toString());
        refType2(strList2);
        System.out.println("now the strList2 is" + strList2.toString());


        List<String> strList3 = new ArrayList<String>();
        strList3.add("hello world 3");
        List<String> strList3Ref = new ArrayList<String>();

        // 4.deep copy
        strList3Ref.addAll(strList3);
        // 5.shallow copy
        strList3.add("hi jude 3");

        System.out.println("now strList3: " + strList3);
        System.out.println("now strList3Ref: " + strList3Ref);
    }

    //1. 修改基本 型變量拷貝的值
    //1.1 在棧內(nèi)存 的新地址中復(fù)制了i的拷貝i',i'的值也是0;
    //1.2 修改了 i'的值為3;
    //1.3 i的值沒有 變化
    private static void byPrimitive(int i) {
        i = i + 3;
        System.out.println("the i' is :" + i);
    }

    //2.修改引用 型變量的拷貝的所引用的對象。
    // 2.1 在棧內(nèi)存 中復(fù)制了strList的拷貝 值,新建了引用strList’,strList’的值等同 于strList的值, 即:指向同樣的一片堆內(nèi)存區(qū)域;
    // 2.2,對strList'引用的對 象做了修改;2.3因為strList所引用的 對象就是strList'所引用的 對象,所以strList的引用對 象發(fā)生了變化。
    private static void refType(List<String> strList) {
        strList.add("hi jude");
        System.out.println("the strList' is :" + strList);
    }

    //3 修改引用 型變量的拷貝的引用。
    //3.1 在棧內(nèi)存 中復(fù)制了strList2的拷貝 值,新建了引用strList2’,strList2'的值等同 于strList2的值, 即:指向同樣的一片內(nèi)存區(qū)域;
    //3.2 對strList2'做修改, 即,使其成為局部變量targetList所引用對 象的引用。
    //3.3 修改strList2'所引用對 象的值,即strList2'所引用對 象發(fā)生了改變,strList2卻沒有變 化。
    private static void refType2(List<String> strList) {
        List<String> targetList = new ArrayList<String>();
        strList = targetList;
        strList.add("hi jude");
        System.out.println("the strList' is :" + strList);
    }

}
  
?

以上代碼中的注釋已經(jīng)基本清晰,第三種種" 修改引用型變量的拷貝的引用"我個人感覺用途很少, 在實際中若是在傳遞值過程中不想改變原有引用的對象,一般都會
先將該變量所引用的對象內(nèi)容先拷貝一份, 然后再對其操作,這樣就不會修改原值。對此,我們會注意到另外一個話題,就
是淺拷貝和深拷貝,在第三點我們再細(xì)述。
上面三種情況的內(nèi)存分配圖如下:

      1. 修改基本 型變量拷貝的值
    


到底是傳值還是傳引用?

?

    2.修改引用 型變量的拷貝的所引用的對象。
  


到底是傳值還是傳引用?

?

        3. 修改引用 型變量的拷貝的引用。
  

到底是傳值還是傳引用?

?

?

?


?

?

3.? 淺拷貝 ? 深拷貝 .

?? ?引用到三方方法時得考慮,such as? Collection.add() 和 collection.addAll(),見代碼4和5部分。

?

4. 為啥會有誤解?

?? ?4.1 一種:因為java中的對象都是靠對象變量即引用來標(biāo)識的,所以參數(shù)傳遞中試引用時,當(dāng)然就是引用傳遞了。

?? ? ? ? ?解釋:如果傳遞了Object reference那么就是by reference,那么對應(yīng)的基本類型(primitive type)的參數(shù)傳遞應(yīng)該就是by primitive ,在這會,reference type 和primitive type是一對對立統(tǒng)一的范疇,在命名上不能顧此失彼吧。歸根到底還是對by reference and by value的定義不清楚,參見我們捋的第一條。

?? ?4.2 另外一種:參數(shù)傳遞中,會改變原來的變量的值,所以是引用傳遞。

?? ? ? ? ?解釋:在 所謂的call by reference中,有時候原變量的值,其所引用的對象存在不改變的情況。參見例子.所以不能成為理由。

?? ?4.3 與C++中的by reference混淆。

?

5. 最后,你實在不相信我說的,也該相信Java他爹說的話吧?

Some people will say incorrectly that objects are passed "by reference. " In programming language design, the term pass by reference properly means that when an argument is passed to a function, the invoked function gets a reference to the original value, not a copy of its value. If the function modifies its parameter, the value in the calling code will be changed because the argument and parameter use the same slot in memory. If the Java programming language actually had pass-by-reference parameters, there would be a way to declare halve it so that the above code would modify the value of one, or so that common Name could change the variable sirius to null. This is not possible. The Java programming language does not pass objects by reference; it passes object references by value. Because two copies of the same reference refer to the same actual object, changes made through one reference variable are visible through the other. There is exactly one parameter passing mode pass by value and that helps keep things simple.

?

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-----Gosling. The Java Programming Language 第2章 第6節(jié)

?

?

?

?

到底是傳值還是傳引用?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 隆林| 贡嘎县| 鄢陵县| 钟祥市| 乡城县| 开江县| 天柱县| 合山市| 阳春市| 永清县| 紫金县| 琼中| 靖宇县| 汶川县| 磐石市| 五华县| 崇礼县| 新田县| 子长县| 邯郸县| 会同县| 商城县| 金平| 图们市| 万荣县| 辽阳县| 阜南县| 依兰县| 洪洞县| 聂拉木县| 交口县| 敦煌市| 民乐县| 沁阳市| 高青县| 长阳| 武宣县| 阿坝| 波密县| 宣化县| 彭山县|