【问题标题】:How can I change Integer value when it is an argument like change array's value? [duplicate]当它是像更改数组值这样的参数时,如何更改整数值? [复制]
【发布时间】:2014-11-28 21:36:36
【问题描述】:
public static void main(String[] args) {
    Integer i = new Integer(0);
    int[] arr = {1};
    p1(i);
    p2(arr);
    System.out.println(i);
    System.out.println(arr[0]);
}


public static void p1(Integer i) {
    i = 2;
}

public static void p2(int[] i) {
    i[0] = 2;
}

//输出:0, 2

如何更改 i 的值,就像更改 arr 的值一样?

【问题讨论】:

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


    【解决方案1】:

    您不能在p1 方法中更改main 中变量i 的值,因为参数是按值传递的:p1 中的参数ii 变量,只是它们在方法开始时具有相同的值。 Java 总是使用按值传递的语义——但是当参数类型是一个类时,它是一个按值传递的引用

    事实上,您也没有更改arr 的值——它是对与以前相同的数组的引用,但数组中的值in 已更改。这就是 Integer 无法做到的,因为 Integer 是不可变类型。

    如果你想要一个像Integer 这样的可变类,你可以改用AtomicInteger

    public static void main(String[] args) {
        AtomicInteger i = new AtomicInteger(0);
        modify(i);
        System.out.println(i);
    }
    
    private static void modify(AtomicInteger x) {
        x.set(2);
    }
    

    我通常不会这样做,但是 - 我通常尽量不修改方法参数引用的对象。相反,我编写了计算单个结果并返回该结果的方法。

    【讨论】:

    • 这不是问题的答案,因为 AtomicInteger 根本不是整数。而你回答错了。参数不是按值传递的。它是通过引用传递的,因为 this 是整数对象(不是原始 int)。
    • @walkeros:不,它真的不是通过引用传递的,因为在Java中没有任何东西通过引用传递。请阅读javadude.com/articles/passbyvalue.htm 或关于这个主题的数百个问题中的一些。我已经解释过 OP 要求的内容不能直接完成,所以我给出了一个 similar (但可变)类型的答案。
    • 任何布尔类型,如 atomicinteger?
    • @cow12331: AtomicBoolean?
    • @walkeros: 不,它不像是通过引用传递一样 - 因为否则在方法中更改i修改调用者的变量。 (这就是按引用传递的全部内容。)请注意,我没有说对象是按值传递的——我说 reference 是按值传递的。恐怕你是误导 - 并且不准确 - 在这里,我声称 Java 使用传递引用。将此与 C# 之类的语言进行比较,后者默认情况下类似于 Java,但也允许使用 ref 修饰符进行引用传递。
    【解决方案2】:

    简单地说:你不能,因为Integer是不可变的,你只能通过值获取对象地址,所以交换整个对象是不可能的,因为方法完成后,旧对象会被重新分配。

    【讨论】:

      【解决方案3】:

      只能通过使用一些“技巧”。你可以这样做:

      public static void p1(Integer curInt) {
                Field field = curInt.getClass().getDeclaredField("value"); // Integer stores the real value in private field "value"
                field.setAccessible(true);
                field.set(curInt, 2);
      
      }
      

      【讨论】:

      • 在这种情况下使用反射是绝对不合适的。
      • @Dimitry:你为什么这么认为?它并不漂亮。没错,但这就是反思的目的。
      • 应该使用反射,其他什么都不能使用。在那里,Integer 可以替换为 AtomicInteger 或者 OP 可以传递数组(不如只使用一些可变的国王 Integer,但也可能)。
      • 很多时候,反射以完全合理的方式很有用。这不是那些时代之一。哎呀,如果您传递了一个小的int 的自动装箱结果,情况会变得更糟,因为这样会在每次自动装箱相同的值时使用变异的(污染的!)对象。像这样的代码应该带有比“仅使用一些黑客”更强烈的健康警告...
      • @walkeros:我宁愿写比 OP 听到的更多内容,而是告诉他们他们需要听到的一切,而不是实际邀请某人做一些非常危险的事情,但没有说明风险。
      【解决方案4】:

      您可以使用AtomicInteger,它允许更改,而不是Integer

      public static void main(String[] args) {
          AtomicInteger i = new AtomicInteger(0);
          p1(i);
          System.out.println(i);
      }
      
      
      public static void p1(AtomicInteger i) {
          i.set(2);
      }
      

      【讨论】:

      • 这对我来说是最好的答案
      猜你喜欢
      • 2021-11-08
      • 2020-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-16
      • 2013-05-11
      • 1970-01-01
      相关资源
      最近更新 更多