<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JAVA到底是值傳遞還是引用傳遞?

          共 7377字,需瀏覽 15分鐘

           ·

          2021-04-29 17:33

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          76套java從入門到精通實戰(zhàn)課程分享

          Java到底是值傳遞還是引用傳遞呢?可能我們背過很多次,說java是值傳遞(當然,網(wǎng)上也有一些同學信誓旦旦的說java是引用傳遞,錯誤),但是當我突然再問你java為什么是值傳遞的?那可能就有點懵了。

          1.形參和實參

          JAVA是一種面向?qū)ο蟮木幊陶Z言,一個類中有屬性和方法,我們這里重點說下方法的定義。

          package com.donkey;

          public class Person {

              private String name;

              private 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;
              }

              public int changeAge(int age) {
                  age = age+1;
                  System.out.println("changeAge方法執(zhí)行后的年齡:" + age);
                  return age;
              }

              public static void main(String[] args) {
                  Person person = new Person();
                  person.changeAge(10);
              }
          }

          我們重點看一下changeAge(int age)這個方法,這是一個有參的方法,在main方法中調(diào)用changeAge方法,并且傳遞參數(shù)age =1;


          說到這里,我要引出兩個概念:形式參數(shù)(形參)和實際參數(shù)(實參);


          形參:是在定義函數(shù)名和函數(shù)體的時候使用的參數(shù),目的是用來接收調(diào)用該函數(shù)時傳入的參數(shù);


          實參:在調(diào)用有參函數(shù)時,主調(diào)函數(shù)和被調(diào)函數(shù)之間有數(shù)據(jù)傳遞關(guān)系。在主調(diào)函數(shù)中調(diào)用一個函數(shù)時,函數(shù)名后面括號中的參數(shù)稱為“實際參數(shù)”。


          如上面的例子中,changeAge(int age)這個方法中的age就是形參,而調(diào)用這個方法時傳遞的10就是實參。


          即:實參是調(diào)用有參方法的時候真正傳遞的內(nèi)容,而形參是用于接收實參內(nèi)容的參數(shù)。


          2.值傳遞與引用傳遞

          通過上面,我們知道了形參和實參,那么在調(diào)用方法的時候,我們怎么傳遞的呢?或者說傳遞的是什么呢?這就引出了下面的概念:值傳遞和引用傳遞。


          值傳遞:調(diào)用函數(shù)時將實際參數(shù)復制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進行修改,將不會影響到實際參數(shù)。


          引用傳遞:指在調(diào)用函數(shù)時將實際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進行的修改,將影響到實際參數(shù)。


          基于上面的理論知識,我們看下面這段程序:

          public static void main(String[] args) {
              Person person = new Person();
              int age = 20;
              person.changeAge(age);
              System.out.println("main方法中的年齡:" + age);
          }

          輸出的結(jié)果為:

          changeAge方法執(zhí)行后的年齡:21
          main方法中的年齡:20

          從結(jié)果可知,changeAge方法并沒有改變實際參數(shù)age的值,實參age還是等于20。所以我們得出結(jié)論:java是值傳遞。


          但真實情況可能并不是這么簡單,因為我們傳遞是一個基本數(shù)據(jù)類型,那如果是傳一個引用類型的實參呢?那再看下面的小程序:

          public String changeName(String name) {
              name = "zhangsan";
              System.out.println("changeName方法執(zhí)行后的名字:" + name);
              return name;
          }

          public static void main(String[] args) {
              Person person = new Person();
              String name ="lisi";
              person.changeName(name);
              System.out.println("main方法中的name:" + name);
          }

          輸出結(jié)果如下:

          changeName方法執(zhí)行后的名字:zhangsan
          main方法中的name:lisi

          顯然,changeName方法并沒有改變實參name的值,main方法中的name還是lisi。所以:java是值傳遞。


          可能你說,你這個實驗的不對,要是傳遞一個對象,就不是這樣的了,那么我們以user為例,再看下面的小程序:

          public void changPerson(Person person) {
              person.setAge(30);
              person.setName("zhangfei");
              System.out.println("changPerson方法執(zhí)行后的person::" + person);
          }

          @Override
          public String toString() {
              return "Person{" +
                      "name='" + name + '\'' +
                      ", age='
          " + age + '\'' +
                      '}';
          }

          public static void main(String[] args) {
              Person person = new Person();
              person.setAge(45);
              person.setName("
          gunayu");
              person.changPerson(person);
              System.out.println("
          main方法中的person:" + person);

          }

          執(zhí)行結(jié)果如下:

          changPerson方法執(zhí)行后的person::Person{name=‘zhangfei’, age=‘30’}
          main方法中的person:Person{name=‘zhangfei’, age=‘30’}

          哦哦哦,這時候你可能會說,看看吧,person的內(nèi)容改變了,這說明java在傳遞對象的時候是引用傳遞。那么這個結(jié)論正確么?如果這個結(jié)論不正確,那它錯在哪里呢?


          3.JAVA中的值傳遞

          通過上面的三個小程序,我們得出來了不同的結(jié)論,這也是我當初怎么也無法理解這個概念的原因。其實上面的理論沒有問題,只是我們實驗的方法由問題。通過上面值傳遞和引用傳遞的概念,我們知道,這兩個的概念的最核心的區(qū)別就是值傳遞過程中或不會重新復制一份副本出來。

          我們再來舉個比較形象的例子。


          當你的同事想開你的車出差,然后你有一把車鑰匙,你直接把這把車鑰匙給了同事。假如這個同時給車鑰匙加了一個鑰匙套,那么當同事把車鑰匙還給你的時候,這把鑰匙就會包裹了一個鑰匙套,這就是引用傳遞。


          當你的同事想開你的車出差,你有一把車鑰匙,然后你找4S店復制了一把車鑰匙,你把新復制的這把車鑰匙給了同事。假如這個同時給車鑰匙加了一個鑰匙套,那么當同事把車鑰匙還給你的時候,你手里的這把原始鑰匙依然沒有鑰匙套,這就是值傳遞。


          下面我們再看看一個小程序:

              public void changPerson1(Person person) {
                  person = new Person();
                  person.setAge(30);
                  person.setName("zhangfei");
                  System.out.println("changPerson1::" + person);
              }
              public static void main(String[] args) {
                  Person guanyu = new Person();
                  guanyu.setAge(45);
                  guanyu.setName("gunayu");
                  guanyu.changPerson1(guanyu);
                  System.out.println("main方法中的person:" + guanyu);

              }


          執(zhí)行結(jié)果如下:

          changPerson1::Person{name=‘zhangfei’, age=‘30’}
          main方法中的person:Person{name=‘gunayu’, age=‘45’}

          當我們在main中創(chuàng)建一個Person對象的時候,在堆中開辟一塊內(nèi)存,其中保存了name和age數(shù)據(jù)。然后guanyu持有該內(nèi)存的地址0x00000001



          當嘗試調(diào)用changPerson1方法,并且guanyu作為實際參數(shù)傳遞給形式參數(shù)person的時候,會把這個地址0x00000001交給person,這時,person也指向了這個地址

          然后在changPerson1方法內(nèi)對參數(shù)進行修改的時候,即person= new Person();,會重新開辟一塊0x00000002的內(nèi)存,賦值給person。后面對user的任何修改都不會改變內(nèi)存0x00000001`的內(nèi)容,

          上面這種傳遞是什么傳遞?肯定不是引用傳遞,如果是引用傳遞的話,在執(zhí)行person= new Person();的時候,實際參數(shù)的引用也應(yīng)該改為指向0x00000001,但是實際上并沒有。


          所以,java在傳遞對象時,傳遞是堆中的那一小塊內(nèi)存區(qū)域,而并不是person這個引用的本身。


          **所以,值傳遞和引用傳遞的區(qū)別并不是傳遞的內(nèi)容。而是實參到底有沒有被復制一份給形參。**在判斷實參內(nèi)容有沒有受影響的時候,要看傳的的是什么,如果你傳遞的是個地址,那么就看這個地址的變化會不會有影響,而不是看地址指向的對象的變化。就像車鑰匙和車的關(guān)系,車鑰匙通過引用執(zhí)行車,所以如果是引用傳遞的話,變化的應(yīng)該是車鑰匙而不是引用的那輛車。


          其實也好理解,guanyu = new Person(),其實完全就可以把那小塊對空間理解成guanyu所對應(yīng)的值。


          4.小結(jié)

          無論是值傳遞還是引用傳遞,其實都是一種求值策略(Evaluation strategy)。在求值策略中,還有一種叫做按共享傳遞(call by sharing)。其實Java中的參數(shù)傳遞嚴格意義上說應(yīng)該是按共享傳遞。


          按共享傳遞,是指在調(diào)用函數(shù)時,傳遞給函數(shù)的是實參的地址的拷貝(如果實參在棧中,則直接拷貝該值)。在函數(shù)內(nèi)部對參數(shù)進行操作時,需要先拷貝的地址尋找到具體的值,再進行操作。如果該值在棧中,那么因為是直接拷貝的值,所以函數(shù)內(nèi)部對參數(shù)進行操作不會對外部變量產(chǎn)生影響。如果原來拷貝的是原值在堆中的地址,那么需要先根據(jù)該地址找到堆中對應(yīng)的位置,再進行操作。因為傳遞的是地址的拷貝所以函數(shù)內(nèi)對值的操作對外部變量是可見的。


          即:Java中的傳遞,是值傳遞,如果是引用類型這個值,實際上傳遞的是對象的引用(即棧與對之間的那條指向的線,每次傳遞時,其實是復制出了這樣一條線,只不過線的起點換成了形參,終點沒有變)。

          ————————————————

          版權(quán)聲明:本文為CSDN博主「泗水長流」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

          原文鏈接:

          https://blog.csdn.net/lvxinchun/article/details/116140524






          粉絲福利:Java從入門到入土學習路線圖

          ??????

          ??長按上方微信二維碼 2 秒


          感謝點贊支持下哈 

          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜国产 码网站 码 | 大奶一区二区三区 | 国产精品卡一卡二 | 国产又粗又猛视频 | 国产伦精品一区二区三区竹菊视频 |