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) 中,你传递给方法的是指向狗的地址的副本,方法中对这个副本的操作并不会影响原始的地址,也就是不会改变原来指向的对象。但是,当你在方法内部把这个副本指向了一个新的对象时,这只是修改了这个副本的值,并不会影响原始的地址。