天天看點

為什麼說java是隻有值傳遞?

為什麼說java是隻有值傳遞?

如果你學的第一門程式語言是java可能對這個傳遞方式沒有那麼敏感,如果學了c或c++,然後再學java,那麼可能對這個問題會感到困惑。

1.值傳遞與引用傳遞的概念

在将傳遞方式之前先了解一下形參與實參。

形式參數:是在定義函數名和函數體的時候使用的參數,目的是用來接收調用該函數時傳入的參數。

實際參數:在調用有參函數時,主調函數和被調函數之間有資料傳遞關系。在主調函數中調用一個函數時,函數名後面括号中的參數稱為“實際參數”。

可以這麼了解:形參是實參的抽象,實參是調用時的參數,形參是定義函數的參數

值傳遞:方法調用時,實際參數把它的值傳遞給對應的形式參數,函數接收的是原始值的一個copy,此時記憶體中存在兩個相等的基本類型,即實際參數和形式參數,後面方法中的操作都是對形參這個值的修改,不影響實際參數的值。

引用傳遞:是指在調用函數時将實際參數的位址直接傳遞到函數中,那麼在函數中對參數所進行的修改,将影響到實際參數。

劃重點:值傳遞和引用傳遞的主要差別

值傳遞

引用傳遞

建立副本,在函數體中不能改變原來的值

不建立副本,在在函數體中不能改變原來的值

建立副本的含義

建立副本也就是說,把要調用的實參先拷貝一份出來,然後用拷貝的那一份傳進函數體内。不建立副本時,不會發生copy這個步驟。

舉個值傳遞的栗子:

複制代碼

1 public class Test01 {

2 public static void main(String[] args) {

3 int a=1,b=2;

4 swap(a, b);

5 System.out.println("a="+a);

6 System.out.println("b="+b);

7 }

8 public static void swap(int a,int b) {

9 int temp=a;

10 a=b;

11 b=temp;

12 }

13 }

結果:

1 a=1

2 b=2

上面栗子中,在函數中讓實作a,b交換,但調用函數後,輸出的結果仍然是a,b原來的值,說明函數體中的操作并不能影響a,b在函數體外的值。

引用傳遞的栗子就不測試了,有興趣的話可以用c++來測試,參數為定義為别名或指針時,在c++中是引用傳遞。

誤區:傳遞的參數如果是普通類型,那就是值傳遞,如果是對象,那就是引用傳遞。這是錯誤的!!!!!

2.java中的值傳遞

在java中,無論參數是基本類型,還是引用資料類型,都是值傳遞方式。下面來舉個引用資料類型的參數,基本資料類型的栗子上面已經有了。

2 public static void swap(Student st1,Student st2) {

3 Student temp=st1;

4 st1=st2;

5 st2=temp;

6 }

7

8 public static void main(String[] args) {

9 Student st1=new Student("張三",20);

10 Student st2=new Student("李四",20);

11 swap(st1, st2);

12 System.out.println("st1:"+st1);

13 System.out.println("st2:"+st2);

14 }

1 st1:Student [name=張三, age=20]

2 st2:Student [name=李四, age=20]

例子中,st1和st2的所指向的對象并沒有發生改變。

這時候,你可能會問,既然java是值傳遞,那麼實參會發生拷貝,那拷貝的是什麼東西呢?答案是:拷貝的是對象在堆中的位址。來個栗子來驗證一下:

2 public static void print(Student stu1,Student stu2) {

3 Student temp=stu1;

4 stu1=stu2;

5 stu2=temp;

6 System.out.println("在函數體中交換後列印stu1: "+stu1);

7 System.out.println("在函數體中交換後列印stu2: "+stu2);

8 }

9

10 public static void main(String[] args) {

11 Student stu1=new Student("stu1",20);

12 Student stu2=new Student("stu2",30);

13 print(stu1, stu2);

14 }

15 }

1 在函數體中交換後列印stu1: Student [name=stu2, age=30]

2 在函數體中交換後列印stu2: Student [name=stu1, age=20]

從結果中可以看出,在函數體中stu1和stu2所指向的對象确實是發生了改變,這是因為在值傳遞的過程中拷貝了他們在堆中的位址。

來看看他們在記憶體中的怎麼樣的:

這時候你可能會問,既然java的值傳遞是拷貝位址,那我能不能改變位址所隻想的内容?答案是:當然可以

1 public static void changeInf(Student stu) {

2 stu.setName("我改名字了");

3 }

4

5 public static void main(String[] args) {

6 Student stu=new Student("張三",18);

7 changeInf(stu);

8 System.out.println(stu);

9 }

1 Student [name=我改名字了, age=18]

結論:java中隻有值傳遞,這可能是因為java沒有指針和别名引用的原因吧。

原文位址

https://www.cnblogs.com/ironHead-cjj/p/11366888.html