12

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

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

这打印出来0, 1,不像0, 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;在最后一行之前添加

4

5 回答 5

15

跨平台使用非常安全。该行为在 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());
于 2012-11-07T23:34:55.380 回答
1

从 Java 1.5 开始,Java 执行自动拆箱以在必要时将“包装器类型”转换为Integer相应的原始类型int。然后增量运算符可以处理结果int

于 2012-11-07T23:34:47.080 回答
1

对于只编程几年或几年的程序员来说,Tedd Hopp 爵士的回答处于非常复杂的水平。

让我以简单的方式消除您的疑问

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

输出将是 11

因为 ++ 后增量或前增量仅在内部进行 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。

于 2019-05-16T19:57:10.690 回答
0

它是 Java 5 中称为自动装箱的“新”功能——整数在需要时转换为 in——反之亦然。同样适用于 Float、Double、Boolean 等。

虽然这是一个方便的功能,但如果您不小心,它可能会导致巨大的性能损失

于 2012-11-07T23:36:18.310 回答
0

请注意,如果将增量操作移至方法,则输出将与预期的一样:

public void printIncrement(Integer x1) {
    System.out.print(x1++ + ", ");
}

这是因为 Java 传递了引用的副本,所以您现在正在使用一个新的引用对象,x1 而不是 x。x 指向的原始 Integer 对象保持不变,x 仍然指向它。

如果您忘记了它,那么在使用方法进行计算时,这很容易咬到您。

于 2018-11-25T08:57:50.377 回答