为什么后增量在包装器类上起作用

2022-09-04 01:47:50

我正在对一些代码进行审查,并遇到了一个实例,有人在递增一个成员变量后,该成员变量是围绕整数的包装类。我自己尝试了一下,真的很惊讶它的工作原理。

Integer x = 0; 
System.out.print(x++ + ", ");
System.out.print(x);

这打印出来了,不像我预期的那样。我已经查看了语言规范,找不到任何涵盖此内容的内容。任何人都可以向我解释为什么这有效,如果它在多个平台上是安全的?我本来以为这会分解成0, 10, 0

Integer x = 0;
int temp1 = x.intValue();
int temp2 = temp1 + 1;
System.out.println(temp1);
temp1 = temp2;
System.out.println(x.intValue());

但显然,规范中有一些东西使它在最后一行之前添加x = temp1;


答案 1

跨平台使用非常安全。该行为在 Java 语言规范的 §15.4.2 中指定(着重号是后加的):

后缀表达式的结果必须是可转换为数值类型 (§5.1.8) 的类型变量,否则会发生编译时错误。

后缀增量表达式的类型是变量的类型。后缀增量表达式的结果不是变量,而是值。

在运行时,如果操作数表达式的计算突然完成,则后缀增量表达式会出于同样的原因突然完成,并且不会发生递增。否则,值 1 将添加到变量的值中,并将总和存储回变量中。在加法之前,对变量的值 1 和值执行二进制数值提升 (§5.6.2)。如有必要,在存储变量之前,通过缩小基元转换 (§5.1.3) 和/或进行装箱转换 (§5.1.7) 到变量的类型来缩小总和。后缀增量表达式的值是存储新值之前的变量值。

编辑下面是示例代码中发生的情况的更准确的等效项:

Integer x = 0;
int temp = x.intValue();
x = temp + 1; // autoboxing!
System.out.println(temp + ", ");
System.out.println(x.intValue());

答案 2

Tedd Hopp爵士的回答对于只编程很少或几年的程序员来说是一个非常复杂的水平。

让我以简单的方式消除您的疑虑,假设

    Integer x=10;
    x++;
    System.out.println(x) ;

输出将为 11

因为 ++ 无论是 post 还是 pre increment 都只在内部执行 1 的加法

即x + 1是它必须执行的,并将结果放回相同的变量中。

ie x=x+1;

现在我们都知道+运算符只能取基元,但x是对象,那么我们有自动解箱和自动装箱的概念。所以表达式变成

x.intValue()+1;//step 1 auto-unboxing

x=Integer.valueOf(x.intValue()+1);//step 2 auto-boxing

因此,在 println 语句中自动拆箱的另一个步骤之后,输出显示为 11。