引用传递

详情

引用传递

  • 当我们传递一个对象(如数组等对象类型)作为参数时,传递的是引用的副本(内存地址的拷贝),而非引用本身。函数对对象进行修改会影响原始对象。

实验一:修改对象内容(成功)→ 证明“共享同一对象”

public class ReferencePassingArray {
 
    public static void modifyArray(int[] arr) {
        System.out.println("方法内部修改前:arr[0] = " + arr[0]);
        arr[0] = 100; // 修改的是引用指向的数组对象的内容
        System.out.println("方法内部修改后:arr[0] = " + arr[0]);
    }
 
    public static void main(String[] args) {
        int[] originalArray = {1, 2, 3};
        System.out.println("调用方法前:originalArray[0] = " + originalArray[0]);
        modifyArray(originalArray); // 将 originalArray 的引用复制一份传递给 modifyArray 方法
        System.out.println("调用方法后:originalArray[0] = " + originalArray[0]);
    }
}

输出结果:

调用方法前:originalArray[0] = 1
方法内部修改前:arr[0] = 1
方法内部修改后:arr[0] = 100
调用方法后:originalArray[0] = 100

解释:

  • main 方法中,originalArray 引用指向一个包含 {1, 2, 3} 的数组对象。
  • 当调用 modifyArray(originalArray) 时,originalArray 这个引用(内存地址)被复制一份传递给了 modifyArray 方法的参数 arr
  • 现在,arroriginalArray 这两个引用都指向同一个数组对象。
  • modifyArray 方法内部,通过 arr[0] = 100; 修改了引用所指向的数组对象的第一个元素。
  • 由于 arroriginalArray 指向的是同一个对象,所以当 modifyArray 方法结束后,main 方法中 originalArray 指向的数组的第一个元素也被修改为 100

实验二:交换引用本身(失败)→ 证明“传的是副本,非引用”

public class SwapFailureDemo {
    static class Person {
        String name;
        Person(String n) { name = n; }
    }
 
    public static void swap(Person a, Person b) {
        System.out.println("【方法内】交换前: a=" + a.name + ", b=" + b.name);
        Person temp = a;
        a = b;      // 仅修改局部变量 a 的指向(副本)
        b = temp;   // 仅修改局部变量 b 的指向(副本)
        System.out.println("【方法内】交换后: a=" + a.name + ", b=" + b.name);
    }
 
    public static void main(String[] args) {
        Person x = new Person("Alice"); // 假设堆地址 0x100
        Person y = new Person("Bob");   // 假设堆地址 0x200
        
        System.out.println("【主函数】调用前: x=" + x.name + ", y=" + y.name);
        swap(x, y); // 传递 x(0x100) 和 y(0x200) 的副本
        System.out.println("【主函数】调用后: x=" + x.name + ", y=" + y.name);
    }
}
【主函数】调用前: x=Alice, y=Bob
【方法内】交换前: a=Alice, b=Bob
【方法内】交换后: a=Bob, b=Alice   // ⚠️ 仅方法内局部变量交换
【主函数】调用后: x=Alice, y=Bob   // ❌ 外部引用完全未变!

内存动态解析

主函数栈帧: 
  x ──[纸条: 0x100]──→ [堆0x100: Alice]
  y ──[纸条: 0x200]──→ [堆0x200: Bob]
 
调用 swap 时(复制纸条):
  a ──[复印纸条: 0x100]──→ [堆0x100: Alice]
  b ──[复印纸条: 0x200]──→ [堆0x200: Bob]
 
swap 内执行 a = b:
  a ──[涂改后: 0x200]──→ [堆0x200: Bob]   ← 仅改复印纸条!
  b ──[涂改后: 0x100]──→ [堆0x100: Alice]
 
方法结束 → 复印纸条销毁
主函数纸条原封不动: 
  x ──[0x100]──→ Alice
  y ──[0x200]──→ Bob

关联网络

演化日志

  • v0.1 (2025-05-18):初始版本
  • v0.2 (2026-01-30):补充关联网络、演化日志、附件参考、待办事项