JAVA按值传递问题总结

34 阅读2分钟
import java.util.ArrayList;
public class Solution {

    public void recursion(ListNode head, ArrayList<Integer> res){
        if(head != null){
            recursion(head.next, res);
            res.add(head.val);
        }
    }

    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> res = new ArrayList<>();
        recursion(listNode,res);
        return result; 
    }
}

不是说:Java 的参数是以值传递的形式传入方法中,而不是引用传递,那么为什么res会一直改变呢。

ChatGPT

在 Java 中,参数传递确实是按值传递的,但对于引用类型的参数,传递的是引用的副本,而不是引用本身。这意味着在方法中修改引用类型参数的内容,会影响到原始引用所指向的对象。

在你的代码中,ArrayList<Integer> 是引用类型,res 是对它的引用的副本。当你调用 recursion 方法时,传递的是 res 的副本,但是这两个副本都指向同一个 ArrayList 对象。所以,当你在 recursion 方法中向 res 添加元素时,实际上也在原始的 ArrayList 中添加元素,因此 result 中包含了从头到尾的节点值。

简而言之,虽然传递的是引用的副本,但仍然指向同一个对象,所以对该对象的修改会在所有引用指向的地方可见。

public class PassByValueExample 
{ public static void main(String[] args) 
{ 
    Dog dog = new Dog("A"); 
    System.out.println(dog.getObjectAddress()); // Dog@4554617c 
    func(dog); 
    System.out.println(dog.getObjectAddress()); // Dog@4554617c
    System.out.println(dog.getName()); // A 
} 

private static void func(Dog dog) 
{ 
    System.out.println(dog.getObjectAddress()); // Dog@4554617c 
    dog = new Dog("B"); 
    System.out.println(dog.getObjectAddress()); // Dog@74a14482
    System.out.println(dog.getName()); // B 
} 
}

* * *


在这个例子中,func(dog) 中的 dog 是一个指向 Dog 对象的引用。这个引用在方法内部被复制了一份,但仍然指向同一个对象。

让我用类似的例子解释一下。假设你有一张地图,dog 是你手中的一张纸,上面写着一个地址,这个地址就是你的狗所在的地方。当你把这张纸(引用)交给别人时,他们也可以找到同样的地方。但如果他们改变了这张纸上的地址(引用),这并不会影响你手中的那张纸。

所以,在 func(dog) 中,你传递给方法的是指向狗的地址的副本,方法中对这个副本的操作并不会影响原始的地址,也就是不会改变原来指向的对象。但是,当你在方法内部把这个副本指向了一个新的对象时,这只是修改了这个副本的值,并不会影响原始的地址。