歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java按值傳遞還是引用傳遞?

Java按值傳遞還是引用傳遞?

日期:2017/3/1 9:21:00   编辑:Linux編程

回顧:

在程序設計語言中,將參數傳遞分為按值調用按引用調用。按值調用:表示方法接收的是調用者提供的。而按引用調用表示方法接收的是調用者提供的變量地址
一個方法可以修改傳遞引用所對應的變量值,而不能修改傳遞值調用所對應的變量值。

Java總是采用按值調用。方法得到的是所有參數值的一個拷貝,特別的,方法不能修改傳遞給它的任何參數變量的內容。

方法參數共有兩種類型:

  • 基本數據類型
  • 對象引用

1. 基本數據類型為參數

查看一下的代碼:

public class ParamTest {
    public static void main(String[] args) {
        int price = 5;
        doubleValue(price);
        System.out.print(price);
    }

    public static void doubleValue(int x) {
        x = 2 * x;
    }
}

【輸出結果】: 5

可以看到,這個方法執行之後,price的值並沒有變化。接下來,看一下doubleValue具體的執行過程為:

  1. x被初始化為price值的一個拷貝,即5
  2. x乘以2後等於10。但是price沒有變化,依然是5
  3. doubleValue執行完後,參數變量不再使用

  

2. 對象引用為參數

從上面的例子我們已經知道一個方法不能修改一個基本數據類型的參數。而對象引用作為參數就不同了。看下面的例子:

class Student {

    private float score;

    public Student(float score) {
        this.score = score;
    }

    public void setScore(float score) {
        this.score = score;
    }

    public float getScore() {
        return score;
    }


}

public class ParamTest {
    public static void main(String[] args) {
        Student stu = new Student(80);
        raiseScore(stu);
        System.out.print(stu.getScore());
    }

    public static void raiseScore(Student s) {
        s.setScore(s.getScore() + 10);
    }
}

【運行結果】:

90.0

可以看出,Student實例s的內容改變了。

具體執行過程為:

  1. s被賦予stu值的拷貝,這裡是一個對象的引用
  2. raiseScore方法應用於這個應用。s和stu指向同一對象,該對象的分數增加了10
  3. raiseScore方法結束後,s不再使用,stu指向的那個對象分數增加了10

3. 對對象是值調用還是引用傳遞?

首先編寫一個交換兩個學生的方法:

public static void swap(Student x, Student y) {
    Student temp = x;
    x = y;
    y = temp;
 } 

如果java對對象是采用的是引用傳遞,那個這個方法是可以的。那麼x,y對象的分數是交換的。看下面的例子:

class Student {

    private float score;

    public Student(float score) {
        this.score = score;
    }

    public void setScore(float score) {
        this.score = score;
    }

    public float getScore() {
        return score;
    }
}

public class ParamTest {
    public static void main(String[] args) {
        Student a = new Student(0);
        Student b = new Student(100);

        System.out.println("交換前:");
        System.out.println("a的分數:" + a.getScore() + "--- b的分數:" + b.getScore());

        swap(a, b);

        System.out.println("交換後:");
        System.out.println("a的分數:" + a.getScore() + "--- b的分數:" + b.getScore());
    }

    public static void swap(Student x, Student y) {
        Student temp = x;
        x = y;
        y = temp;
    }
}

【運行結果】:

交換前:
a的分數:0.0--- b的分數:100.0
交換後:
a的分數:0.0--- b的分數:100.0

可以看出,兩者並沒有實現交換。說明引用傳遞的說法是不正確的。接下來一步一步看看swap調用的過程:

  1. 將對象a,b的拷貝分別賦值給x,y,此時a和x指向同一對象,b和y指向同一對象
  2. swap方法體完成x,y的的交換,此時a,b並沒有變化
  3. 方法執行完成,x和y不再使用,a依舊指向new Student(0),b指向new Student(100)

首先,創建兩個對象:

然後,進入方法體,將對象a,b的拷貝分別賦值給x,y:

接著,交換x,y的值:

swap執行完成,x,y不再使用,回到創建時狀態。

從這個過程中可以看出,Java對對象采用的不是引用調用,實際上,對象引用進行的是值傳遞。

總結一下java中方法參數的使用情況:

  • 一個方法不能修改一個基本數據類型的參數(即數值型和布爾型)
  • 一個方法可以改變一個對象參數的狀態
  • 一個方法不能讓對象參數引用一個新的對象

Copyright © Linux教程網 All Rights Reserved