java中~和++的优先级
Posted
技术标签:
【中文标题】java中~和++的优先级【英文标题】:precedence of ~ and ++ in java 【发布时间】:2013-05-05 07:35:51 【问题描述】:考虑一下这段代码 sn -p
int j = 7;
System.out.println(Integer.toBinaryString(j));
j = ~j++;
System.out.println(Integer.toBinaryString(j));
打印
111
11111111111111111111111111111000
我期待看到什么
111
11111111111111111111111111111001
首先我认为它可能是 ~ 和 ++ 的优先级
如果 ~ 在 ++ 之前被评估 答案将是
11111111111111111111111111111001
如果 ++ 在 ~ 之前被评估,则为 else
11111111111111111111111111110111
我搜索了Oracle tutorials,但找不到答案。 谁能解释这种行为?
【问题讨论】:
没有人应该这样写代码。 你试过j = ~(++j)
并比较了吗?
Hm...这是Java中定义的行为吗?您正在更改作业两边的 j 。我认为即使您尝试了j=j++
,您也可能会得到意想不到的结果。所以这实际上不是优先级问题。
@Axel 这是 Java 中定义明确的行为。有些毫无意义且通常令人困惑,但绝对定义明确。 Java 并不真正在 undefined behaviour 的业务中。
@Axel, @Dukeling:我查了一下是肯定的,Dukeling 是正确的。规范解决了这种歧义,规范为赋值操作提供了特定的评估顺序。以下链接显示了外部的操作顺序,j = ...
赋值操作:Java Spec section 15.26.1 我没有看到明确说明的行为类似于:j = ++j + j--;
在这种情况下,是 ++ j 在 j++ 之前还是之后评估?每个虚拟机都一样吗?
【参考方案1】:
不要忘记 '++' 后增量运算符返回 j 的值 before 增量发生。也就是说,如果 'j' 为 7,则 'j++' 将 j 设置为 8,但返回 7。 ~7 就是你看到的输出,以三个 0 位结尾的数字。
“++”后增量运算符只能对所谓的“L 值”进行操作。 L 值是实际存在于代码可以逻辑引用的某个位置的值——变量、数组元素、参数或类字段。只要你取一个 L 值的值并对它应用一些数值运算,你就会得到一个 R 值。 R 值 只是 值,它们不引用任何可以放置结果的持久存储。您可以分配给 L 值,但不能分配给 R 值——因此,如果您尝试 '++' 一个 R 值,您会得到一个编译错误。
如果 '~' 运算符先行,那么您将 ++-ing 一个 R 值,如 (~j)++。这不会编译。代码完全编译的事实意味着优先级是另一种方式:~(j++)。
这样的括号是我所知道的最简单的方法,只要有任何混淆,您就可以整理优先级:只需编写三个测试用例:
-
您不确定的原始方式。
使用括号强制执行一种操作顺序。
使用括号强制执行其他操作顺序。
运行它并查看#2 或#3 是否产生与#1 相同的结果。 :-)
【讨论】:
正如你提到的 j = (~j)++ 给出编译错误 ~(j++) 等同于 ~j++,因为 ++ 具有更高的优先级 +1 非常好的答案,尤其是提到 r-value / l-value。【参考方案2】:这两个运算符都是右结合二阶运算符,但一个简单的测试表明它首先执行的是++
,而后者是 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
【讨论】:
【参考方案3】:从右到左计算一元运算符(++1
、--
、+
、-
、~
、!
)。因此++
在~
之前被评估。
【讨论】:
【参考方案4】:代码看起来很脆弱。我认为正在发生的事情是,当评估表达式“~i++”时,提取值“~i”,执行“i++”,然后最终赋值(覆盖“i++”中的先前值)。
【讨论】:
~8 是 11111111111111111111111111110111,而不是 11111111111111111111111111111000。编辑:我看到你的编辑:-) 但是,你仍然有倒序。 ++ 先发生,但 ++ 的结果是 7 而不是 8。 容易与 -8 混淆。我一时糊涂,觉得这个答案是对的。 是的,一开始很困惑。在回答之前应该多考虑一下。 这个答案可能有点准确,但如果是,则不太可能被正确理解。请阅读Jonathan's answer 了解更多信息。【参考方案5】:首先,不要那样做。没有理由将这样的操作符集中到一个语句中,但我意识到您并没有真正打算将其放入实时代码中,而只是在进行试验。试试这个页面以获得 Java 运算符优先级:http://bmanolov.free.fr/javaoperators.php
【讨论】:
如链接中所述,后缀增量在〜之前进行评估,那么答案应该首先是增量:00.....01000 然后补码:11.....10111 这应该是一个评论,除非你真的从链接中提取所需的信息并将其发布在答案中并附上解释。 请解释我是否在链接中没有注意到我可以提取的 ++(前缀或后缀增量)的优先级高于 ~ 并且它们都具有正确的关联性跨度>以上是关于java中~和++的优先级的主要内容,如果未能解决你的问题,请参考以下文章