gpt4 book ai didi

java - 包装到另一个类中的不可变整数(按值调用)

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:23:56 26 4
gpt4 key购买 nike

我想知道在 Java 中按值调用并尝试了一些代码。

public class Test {
public static void main(String[] args) {
Test test = new Test();
Integer integer = 4;
System.out.println(integer);
test.change(integer);
System.out.println(integer);
}

public void change(Integer integer) {
integer++;
}
}

因为 java 是按值调用的,所以我在徘徊输出:

4
5

但是打印出来了

4
4

然后我了解到整数是不可变的,所以我的方法“更改”创建了值为 5 的新整数,而 main 中的“整数”仍然是 4。

然后我写了下面的类:

public class Test {
public static void main(String[] args) {
Test test = new Test();
MyInteger myInteger = new MyInteger();
myInteger.x = 4;
System.out.println(myInteger.x);
test.change(myInteger);
System.out.println(myInteger.x);
}
public void change(MyInteger myInteger) {
myInteger.x++;
}
}
class MyInteger {
Integer x;
}

现在输出就像我最初预期的那样

4
5

这是我的论文:

方法 change(Integer integer) 通过创建一个新的不可变 Integer 代替 Integer x 来修改 myInteger 对象>,并且此方法中的参数 myInteger 始终指向 MyInteger 的同一实例。我对吗?

最佳答案

让我们做一些分析并深入研究这两种方法的字节码。

public class Main {

public static void main(String[] args) {
Main test = new Main();
Integer integer = 4;
System.out.println(integer);
test.change(integer);
System.out.println(integer);
}

public void change(Integer integer) {
integer++;
}
}

change 方法的字节码是:

public change(Ljava/lang/Integer;)V
L0
LINENUMBER 14 L0
ALOAD 1
ASTORE 2
ALOAD 1
INVOKEVIRTUAL java/lang/Integer.intValue ()I // gets value of wrapped int
ICONST_1 // load 1 into stack
IADD // add 1 to your value
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; // return
DUP
ASTORE 1
ASTORE 3
ALOAD 2
POP

如您所见,该值递增并...然后丢失,因为它没有返回。所以我们需要返回这个值才能得到结果,对吧?。

有人会认为以下代码的输出将是 4, 5:

public class Main {
public static void main(String[] args) {
Main test = new Main();
Integer integer = 4;
System.out.println(integer);
Integer integerNew = test.change(integer);
System.out.println(integerNew);
}

public Integer change(Integer integer) {
return integer++;
}
}

输出为 4, 4

为什么?因为这是后增量。您递增了一个新的 Integer 并返回了旧的。分析字节码证实了这一点:

public change(Ljava/lang/Integer;)Ljava/lang/Integer;
L0
LINENUMBER 14 L0
ALOAD 1
ASTORE 2 // store the copy of the first Integer (4)
ALOAD 1 //
INVOKEVIRTUAL java/lang/Integer.intValue ()I // get value of first
ICONST_1 // load 1
IADD // add 1
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; // get modified value Integer (5)
DUP
ASTORE 1 // save it
ASTORE 3
ALOAD 2 // load the copy Integer (4)
ARETURN // return it

因此,我们可以看到 Integer 的值递增并...再次丢失,因为我们返回的值处于递增之前的状态。

预增量就是我们要找的:

public Integer change(Integer integer) {
return ++integer;
}

字节码是:

public change(Ljava/lang/Integer;)Ljava/lang/Integer;
L0
LINENUMBER 14 L0
ALOAD 1 // Integer (4)
INVOKEVIRTUAL java/lang/Integer.intValue ()I
ICONST_1 // load 1
IADD // becomes Integer (5)
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
DUP
ASTORE 1 // save it
ARETURN // return Integer (5)

该值在返回之前增加了,我们可以接受它。

分析最后一个案例:

public class Main {

public static void main(String[] args) {
Main test = new Main();
MyInteger myInteger = new MyInteger();
myInteger.x = 4;
System.out.println(myInteger.x);
test.change(myInteger);
System.out.println(myInteger.x);
}

public void change(MyInteger integer) {
integer.x++;
}
}

class MyInteger {
Integer x;
}

及其字节码:

public change(Lcom/test/MyInteger;)V
L0
LINENUMBER 15 L0
ALOAD 1
ASTORE 2
ALOAD 2
GETFIELD com/test/MyInteger.x : Ljava/lang/Integer; // get Integer (4)
ASTORE 3 // store copy of Integer value (4)
ALOAD 2
ALOAD 2
GETFIELD com/test/MyInteger.x : Ljava/lang/Integer; // get Integer (4)
INVOKEVIRTUAL java/lang/Integer.intValue ()I
ICONST_1
IADD // add 1
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
DUP_X1
PUTFIELD com/test/MyInteger.x : Ljava/lang/Integer; // PUT Integer (5) BACK!
ASTORE 4
ALOAD 3
POP

如您所见,从 PUTFIELD 行开始,MyInteger 实例开始保存对 Integer 的引用,其值为 5.

希望这能帮助您了解有关该主题的更多详细信息。

关于java - 包装到另一个类中的不可变整数(按值调用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50131156/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com