java形參、實參、值傳遞、引用傳遞


工作中,發現大多數人對值傳遞,引用傳遞理解不深,下面寫一遍文章詳細聊聊。

一、形參

形參:用來接收調用方法時傳遞的參數,只有在被調用時才分配內存,一旦調用結束,就釋放內存空間。因此僅在方法內有效。

public void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

這里a,b就是形參,方法結束時,在棧空間就會被銷毀。

二、實參

調用上面方法swap(6, 8); 其中6 8就是實參。

三、值傳遞和引用傳遞

  • 值傳遞:方法調用時,實際參數將它的值傳遞給形式參數,函數就收到的是原始值的副本,此時內存中存在兩個相同的基本類型,若方法中對形參執行處理操作,並不會影響實際參數的值。
  • 引用傳遞:方法調用時,實際參數的引用(指內存地址,不是參數的值)被傳遞給方法中相應的形式參數,函數接受到的是原始值的內存地址,在方法中,形參和實參的內容(地址)相同,方法中對形參的處理會影響實參的值。

public class People {

    private String name;
    private String age;

    public People(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}


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

        int a = 10;
        // 按值傳遞
        test1(a);
        System.out.println("main a==" + a);
        People p = new People("rose", "18");
        // 按引用傳遞
        test2(p);
        System.out.println("main name==" + p.getName() +", age==" + p.getAge());
    
    }

    public static void test1(int a) {
        a = 20;
        System.out.println("test1 a==" + a);
    }

    public static void test2(People p) {
        p.setName("jack");
        p.setAge("19");
        System.out.println("test2 name==" + p.getName() +", age==" + p.getAge());
    }
}

輸出結果:
test1 a==20
main a==10
test2 name==jack, age==19
main name==jack, age==19

結論:

  • 形參為基本類型時,對形參的處理不會影響實參。
  • 形參為應用類型時,對形參的處理會影響實參。
  • String、Integer、Double等immutable類型,因為本身沒有提供修改函數的操作,每次操作都是生成一個新對象,所以要特殊對待,可以理解為值傳遞,形參操作不會影響實參對象。

四、java對象及引用

以上面的People為例,構建一個對象:People p1 = new People("jack", "19");
其實這個對象包含四個動作。

  • 右邊的new People,是以People類為模板,在堆空間創建一個People類對象。
  • 末尾的("jack", "19"),指的是對象創建后,調用的構造函數,對剛生成的對象進行初始化。
  • 左邊的People p1創建了一個People類引用變量,所謂People類引用,就是以后可以用來指向People對象的引用。
  • = 操作符使對象引用指向剛創建的People對象。
People p1;
p1 = new People("jack", "19");
上面兩條語句等價於 People p1 = new People("jack", "19");

這樣看就很明白,一個是對象應用變量,一個是對象實體。
如果只執行第一條,還沒執行第二條此時創建的p1還沒指向任何一個對象,它的值是null。

再來一句:
People p2;
p2 = p1;
這里發生了復制行為,對象本身沒有復制,被復制的只是對象的引用。結果是p2也指向了p1的對象。

再來一句:
p2 = new People("rose", "18");
此時p2指向了第二個對象,此時得出結論:
一個對象引用可以指向0個或者1個對象。
一個對象可以有N個引用指向它。

再來一句:
p1 = p2;
此時p1指向p2這個對象,至於之前的p1這個對象,它已成為垃圾回收機制的處理對象。


四、java中方法參數的引用傳遞

“當一個對象被當作參數傳遞到一個方法”,這就是所謂的引用傳遞。

public class Base2 {
    public static void main(String[] args) {
        People p = new People("jordon","23");
//        changePeople1(p);
        changePeople2(p);
        System.out.println(p.getName() + "===" + p.getAge());
    }

    public static void changePeople1(People p) {
        p.setName("kobe");
        p.setAge("24");
    }

    public static void changePeople2(People p) {
        p.setName("kobe");
        p.setAge("24");

        p = new People("james", "24");
    }
}

以上代碼調用changePeople1和changePeople2都是輸出
kobe===24
我們來分析下為什么了??


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM