【问题标题】:Java considering List argument as referenceJava 将 List 参数作为参考
【发布时间】:2014-06-04 07:52:11
【问题描述】:

我在做一些 RnD 我遇到了这个差异

我的java 代码如下

public class Main {    
public static void main(String[] args) {
    Integer x = 10;
    increment(x);
    System.out.println("print x" + x);

    List<String> strList = new ArrayList<String>();

    strList.add("one");
    strList.add("two");
    strList.add("three");
    strList.add("four");
    strList.add("five");
    strList.add("six");
    System.out.println("Before removing");
    for (String string : strList) {
        System.out.println("item " + string);
    }

    removeSomeItem(strList);
    System.out.println("After removing");
    for (String string : strList) {
        System.out.println("item " + string);
    }

}

private static void removeSomeItem(List<String> strList) {
    strList.remove(0);
    strList.remove(4);
}

private static void increment(Integer x) {
    x++;
    }
}

我得到了上面的代码如下

print x10
Before removing
item one
item two
item three
item four
item five
item six
After removing
item two
item three
item four
item five

我的问题是,当我发送 Integer 来运行它时,它的行为方式与我发送 List&lt;String&gt; 时的行为方式相同,它的行为方式类似于参考,为什么会有这种差异? 谁能解释一下

【问题讨论】:

标签: java pass-by-reference pass-by-value


【解决方案1】:

主要区别在于 Integer 类是不可变的,因此您看不到 main 方法的变化。

x++; // this will simply return a new Integer

要查看差异,请从您的主要方法中尝试:

x = increment(x);

并在增量方法中,将其更改为:

return x++;

但是,对于您的列表示例,您只是将引用的副本传递给列表。只要该引用未设置为新对象(它不是),它就能够更新您传递的原始列表。

【讨论】:

  • 它将 x 的值增加 1,对吗? x++ 等价于 x = x + 1
  • 是的,但不是针对您传递的原始对象引用,它创建了一个新对象,该对象在方法结束时立即丢弃。
  • 谢谢@JamesB,所以你是说每当我们发送列表时,它都是参考而不是价值
  • @SharanabasuAngadi 你会得到一份参考资料。我知道术语令人困惑,但 Java 中的所有内容都是按值传递的。
【解决方案2】:

这正是发生的事情

private static Integer b;

public static void main(String[] args) {
    Integer x0 = 10;
    b = x0;
    increment(x0);
}

private static void increment(Integer x1) {
    //x1 == b is true
    x1++;  //implies x1 = x1 + 1;
    //x1 == b is now false
    //at the end of the day, you've done nothing to x0 or b
}

编辑:此代码将失败,因为显然 JVM 正在缓存 -128 和 127 之间的整数值,see here,设置 x0 = 150 并进行测试。

public class Main {

    static Integer b;

    public static void main(String[] args) {
        Integer x = 150;
        b = x;
        increment(x);
    }

    private static void increment(Integer x) {
        System.out.println(x == b); //true
        x++;
        System.out.println(x == b);  //false
        b++;
        System.out.println(x == b);  //false
    }

}

【讨论】:

    【解决方案3】:

    万一,

    removeSomeItem(strList);
    

    您将原始 ArrayList 的地址传递给该方法,因此当它使用该引用删除某些值时,原始 ArrayList 也会发生变化(实际上它们是具有两个访问点的单个对象,我的意思是引用)。

    但在 Integer 的情况下,您还传递了引用,并且 increment(Integer x) 方法接收原始引用。但是当我做类似的事情时,整数是不可变的,

    x++;
    

    在后台它的工作就像

    x=new Integer(x+1);
    

    这就是为什么当ArrayList发生变化时,原来的Integer保持不变。

    【讨论】:

      猜你喜欢
      • 2021-02-23
      • 1970-01-01
      • 2019-12-28
      • 1970-01-01
      • 2019-06-14
      • 2010-11-02
      • 2014-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多