8

考虑这个代码片段

int j = 7;
System.out.println(Integer.toBinaryString(j));
j = ~j++;
System.out.println(Integer.toBinaryString(j));

印刷

111
11111111111111111111111111111000

我期待看到什么

111
11111111111111111111111111111001

首先我认为它可能是 ~ 和 ++ 的优先级

如果 ~ 在 ++ 之前被评估,答案将是

11111111111111111111111111111001

否则,如果 ++ 之前评估过 ~

11111111111111111111111111110111

我搜索了Oracle 教程,但找不到答案。谁能解释这种行为?

4

5 回答 5

7

不要忘记 '++' 后增量运算符在增量发生之前返回 j 的值。也就是说,如果 'j' 为 7,则 'j++' 将 j 设置为 8,但返回 7。~7 是您看到的输出,数字以三个 0 位结尾。

'++' 后增量运算符只能对所谓的“L 值”进行操作。L 值是实际存在于代码可以逻辑引用的某个位置的值——变量、数组元素、参数或类字段。只要你取一个 L 值的值并对它应用一些数值运算,你就会得到一个 R 值。R 值只是值,它们不引用任何可以放置结果的持久存储。您可以分配给 L 值,但不能分配给 R 值——因此,如果您尝试 '++' 一个 R 值,您会得到一个编译错误。

如果 '~' 运算符先行,那么您将 ++-ing 一个 R 值,如 (~j)++。这不会编译。代码完全编译的事实意味着优先级是另一种方式:~(j++)。

像这样的括号是我所知道的最简单的方法,只要有任何混淆,您就可以整理优先级:只需编写三个测试用例:

  1. 您不确定的原始方式。
  2. 用括号强制一种操作顺序。
  3. 用括号强制执行其他操作顺序。

运行它并查看#2 或#3 是否产生与#1 相同的结果。:-)

于 2013-05-10T15:10:37.600 回答
1

代码看起来很脆弱。我认为正在发生的事情是,当评估表达式“~i++”时,提取值“~i”,执行“i++”,然后最终赋值(覆盖“i++”中的先前值)。

于 2013-05-10T15:09:12.357 回答
1

这两个运算符都是右结合二阶运算符,但一个简单的测试表明它是第一个++执行的,而 BITWISE NOT 运算是后者。

int j = 7, z = 7, k = 7;
z = z++;
z = ~z;
k = ~k++;
j = ~j;
j++;
System.out.println(Integer.toBinaryString(z));
// 11111111111111111111111111111000
System.out.println(Integer.toBinaryString(j));
// 11111111111111111111111111111001
System.out.println(Integer.toBinaryString(k));
// 11111111111111111111111111111000
于 2013-05-10T15:12:43.740 回答
1

一元运算符 ( ++1, --, +, -, ~, !) 从右到左计算。因此++在 之前进行评估~

于 2013-05-10T15:19:01.203 回答
0

首先,不要那样做。没有理由将这样的操作符集中到一个语句中,但我意识到您并没有真正打算将其放入实时代码中,而只是在进行试验。试试这个页面的 Java 运算符优先级:http: //bmanolov.free.fr/javaoperators.php

于 2013-05-10T15:06:50.643 回答