Java 为什么List即使不是全局变量也要更新?

Java 为什么List即使不是全局变量也要更新?,java,methods,global-variables,Java,Methods,Global Variables,AllPath是FindPath中定义的列表>。。。调用dfs的方法。。。方法在其范围内,但我不明白为什么要更新AllPath,因为它不是全局变量?那么,调用dfs方法后,如何更新所有路径列表 import java.util.*; class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } }; class FindAllTreePaths {

AllPath是FindPath中定义的列表>。。。调用dfs的方法。。。方法在其范围内,但我不明白为什么要更新AllPath,因为它不是全局变量?那么,调用dfs方法后,如何更新所有路径列表

import java.util.*;

class TreeNode {
  int val;
  TreeNode left;
  TreeNode right;

  TreeNode(int x) {
    val = x;
  }
};

class FindAllTreePaths {
  public static List<List<Integer>> findPaths(TreeNode root, int sum) {
    List<List<Integer>> allpaths = new ArrayList<List<Integer>>();
    List<Integer> cpath = new ArrayList<Integer>();
    dfs(root, sum, cpath, allpaths);
    return allpaths;
  }
  private static void dfs(TreeNode root, int sum, List<Integer> cpath, List<List<Integer>> result){
    if(root == null){
      return;
    }
    if(root.val == sum && root.left == null && root.right == null){
      cpath.add(root.val);
      result.add(cpath);
    }
    List<Integer> temp = new ArrayList<Integer>();
    temp.addAll(cpath);
    temp.add(root.val);
    dfs(root.left, sum-root.val, temp, result);
    dfs(root.right, sum-root.val, temp, result);
  }

  public static void main(String[] args) {
    TreeNode root = new TreeNode(12);
    root.left = new TreeNode(7);
    root.right = new TreeNode(1);
    root.left.left = new TreeNode(4);
    root.right.left = new TreeNode(10);
    root.right.right = new TreeNode(5);
    int sum = 18;
    List<List<Integer>> result = FindAllTreePaths.findPaths(root, sum);
    System.out.println("Tree paths with sum " + sum + ": " + result);
  }
}
结果是: c=100

这表明c对call1不是全局的

编辑: 我尝试了以下代码,因为我被告知引用类型变量遵循pass-by-reference,但事实并非如此:

public class Main {
    public static void main(String[] args) {
        call();
    }

    public static void call(){
        String c="Jack";
        List<Integer> l = new ArrayList<Integer>();
        l.add(1);
        call1(c, l);
        System.out.println(c);
        System.out.println(l.get(0) + " " + l.get(1));
    }

    private static void call1(String c, List<Integer> l){
        l.add(2);
        c="Jack Ryan";
    }
}
但结果是: 杰克 1 2


这意味着字符串是按值传递的,列表是按引用传递的。

这就是所有基本数据类型int、double、。。。和参考资料。 创建变量时,每次将该变量传递给另一个方法时,都会复制该变量的值。基本数据类型和引用之间的区别在于,它们存储哪些值

基本数据类型 直接存储值,例如数字。传递变量时,会复制该数字

工具书类 处理对象时,实际上是处理对对象的引用。一个存储对象的变量实际上存储了一个引用,就像这个对象的地址一样。将此变量传递给另一个方法时,只复制此对象的地址,这意味着两个方法在内存中使用完全相同的对象


这就是为什么您使用ints的示例可以按预期工作的原因。如果要实际克隆对象,必须实现可克隆的java.lang.Cloneable接口。

使用add显式地对其进行变异,这有什么奇怪的?变量AllPath是在类级别定义的。“dfs”方法也是该类的成员。类方法可以访问和改变类的其他成员。这在Java中是可以预期的。听起来您可能来自另一种语言欢迎使用Java如果是的话:。我建议阅读Java中的变量作用域、修饰符(如static)、引用类型和基本变量之间的差异等。这些都是Java程序员早期需要理解的重要概念。一个很好的资源,即使有点过时:@KellyM Java是按值传递的,但由于List是一个类,这就是为什么它是按引用传递的?如果是这样,String也是一个类对象,那么String对象不应该在其作用域内调用的方法中进行更新吗?@Rohan,Java是按值传递的。传递的是指向对象的指针,而不是对象本身。对列表的更改仍然存在,因为您正在改变对象的状态。对字符串的更改不会保留,因为您正在执行重新分配,而且字符串在Java中是不可变的。这篇文章比我解释得更好:@KellyM谢谢你!若你们有机会的话,你们是否愿意回顾一下下面的帖子:String是引用类型,尽管passby引用并没有被应用。在我的原始帖子中的支持代码中,我尝试用字符串变量替换int,但它使用了预期的传递值的概念。
public class Main {
    public static void main(String[] args) {
        call();
    }

    public static void call(){
        String c="Jack";
        List<Integer> l = new ArrayList<Integer>();
        l.add(1);
        call1(c, l);
        System.out.println(c);
        System.out.println(l.get(0) + " " + l.get(1));
    }

    private static void call1(String c, List<Integer> l){
        l.add(2);
        c="Jack Ryan";
    }
}