• 作者:老汪软件技巧
  • 发表时间:2024-09-27 21:02
  • 浏览量:

大家好,这里是小奏,觉得文章不错可以关注公众号小奏技术

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对象也会发生变化

引用传递java__golang值传递和引用传递

因为现在我们指向的是同一个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