切換語言為:簡體
Java值傳遞和引用傳遞與golang的一些區別

Java值傳遞和引用傳遞與golang的一些區別

  • 爱糖宝
  • 2024-09-25
  • 2037
  • 0
  • 0

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");  // 不會影響原物件
    }
}

這裏分兩種情況

  1. 我們透過引用修改物件的欄位,原始物件也被修改了

  2. 我們嘗試重新賦值物件,但是原始物件並沒有被改變

為什麼會這樣呢?我們簡單透過圖片理解一下

首先在main方法中 我們建立了一個s物件,s指向了一個Student物件

Java值傳遞和引用傳遞與golang的一些區別

然後我們呼叫updateName方法,s的引用被複制並傳遞給方法,但是main方法中的s還是指向原來的Student物件

然後我們透過修改引用的Student實際物件的值,外面的Student物件也會發生變化

Java值傳遞和引用傳遞與golang的一些區別

因為現在我們指向的是同一個Student物件

然後我們呼叫updateStudent方法,s的引用被複制並傳遞給方法,但是我們在方法中將s的引用修改爲指向新的Student物件,但是main方法中的s還是指向原來的Student物件

所以即使修改了引用的Student物件,外面的Student物件並不會發生變化

Java值傳遞和引用傳遞與golang的一些區別

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

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.