java
基本型別
在 Java 中,基本資料型別(如 int, float, boolean 等)是值傳遞
public class ValuePassExample { public static void main(String[] args) { int x = 10; changeValue(x); System.out.println(x); // 輸出 10,x 的值沒有改變 } static void changeValue(int num) { num = 20; } }
引用型別(物件)
在 Java 中,引用型別是引用傳遞,我們來看看幾個例子
jdk提供的物件
public class ReferencePassExample { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); changeValue(sb); System.out.println(sb); // 輸出 "Hello XiaoZou",sb 被修改了 } static void changeValue(StringBuilder s) { s.append(" XiaoZou"); } }
這裏可以看到透過改變引用物件的值,原始物件也被改變了
自定義物件
class Student { String name; Student(String name) { this.name = name; } } public class Main { public static void main(String[] args) { Student s = new Student("xiaozou"); // 情況 1: 修改物件的欄位 updateName(s); System.out.println(s.name); // 輸出 java // 情況 2: 嘗試重新賦值物件 updateStudent(s); System.out.println(s.name); // java } public static void updateName(Student student) { student.name = "java"; // 修改成功 } public static void updateStudent(Student student) { student = new Student("xiaozou"); // 不會影響原物件 } }
這裏分兩種情況
我們透過引用修改物件的欄位,原始物件也被修改了
我們嘗試重新賦值物件,但是原始物件並沒有被改變
為什麼會這樣呢?我們簡單透過圖片理解一下
首先在main
方法中 我們建立了一個s物件,s指向了一個Student物件
然後我們呼叫updateName
方法,s的引用被複制並傳遞給方法,但是main方法中的s
還是指向原來的Student物件
然後我們透過修改引用的Student
實際物件的值,外面的Student
物件也會發生變化
因為現在我們指向的是同一個Student
物件
然後我們呼叫updateStudent
方法,s的引用被複制並傳遞給方法,但是我們在方法中將s的引用修改爲指向新的Student
物件,但是main方法中的s
還是指向原來的Student物件
所以即使修改了引用的Student
物件,外面的Student
物件並不會發生變化
GO
Go 語言只有值傳遞,但是可以透過指標來模擬引用傳遞的效果
值傳遞
package main import "fmt" func main() { x := 10 changeValue(x) fmt.Println(x) // 輸出 10 } func changeValue(num int) { num = 20 }
使用指標模擬引用傳遞
package main import "fmt" type Student struct { Name string } func main() { s := Student{Name: "Alice"} // 情況 1: 傳遞指標,修改結構體欄位 updateName(&s) fmt.Println(s.Name) // 輸出 "Bob" // 情況 2: 傳遞指標,嘗試重新賦值 updateStudent(&s) fmt.Println(s.Name) // 輸出 "Charlie" } func updateName(student *Student) { student.Name = "Bob" // 修改成功 } func updateStudent(student *Student) { *student = Student{Name: "Charlie"} // 修改成功 }
在 Go 中,如果你想在函式內部修改傳入的物件,你需要傳遞該物件的指標。透過指標,你可以修改物件的欄位,甚至可以完全替換該物件。
總結
在Java
中弱化了指標的概念,已經沒有指標了。所以有時候我們進行一些物件的update操作會感覺很奇怪
比如像上面的例子,明明都是修改s,一個影響到了原物件,一個卻沒有影響到原物件
實際我們要區分這兩種情況,雖然都是複製了一個引用
golang
中就不一樣,如果你不定義指標,那麼你就只能進行值傳遞,不管你如何修改,都改變不了原物件
想要修改原物件,你就必須需要傳遞指標,方法定義中的引數就必須是指標比如*Student