爲什麼說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中,無論參數是基本類型,還是引用數據類型,都是值傳遞方式。下面來舉個引用數據類型的參數,基本數據類型的栗子上面已經有了。

複製代碼
1 public class Test01 {
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是值傳遞,那麼實參會發生拷貝,那拷貝的是什麼東西呢?答案是:拷貝的是對象在堆中的地址。來個栗子來驗證一下:

複製代碼
1 public class Test01 {
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章