根据the Oracle operator precedence specification,操作如:
x-- // Returns x, then subtracts 1 from x.
应优先于:
--x // Subtracts 1 from x, then returns x.
所以,鉴于下面的小片段,为什么:
int x = 5;
int y = --x * 5 + x--;
System.out.println(x+" vs "+y);
打印3 vs 24
而不是3 vs 20
?
精化
假设运算符优先级的给定顺序,可以将代码段的第2行分解为以下伪块(先前评估的值放在方括号中):
评估x--
评估--x
评估[--x] * 5
评估[--x * 5] + [x--]
评估y = [--x * 5 + x--]
然后解决如下:
1 returns 5
sets x to 4
2 sets x to 3
returns 3
3 multiplies 3 by 5 and returns 15
4 adds 15 to 5 and returns 20
5 sets y to 20
为什么返回值为24而不是20。
P.S。 (如果在x--之前评估-x,则得到24,但由于运算符优先级而不应该是这种情况。)
我是盲目的还是只是擅长数学或什么?
答案 0 :(得分:5)
无论优先级规定的操作顺序如何,操作符的操作数始终从左到右进行评估。
以下是发生的事情:
--x
。将x
设置为4
,产生4
。(--x) * 5
。此时x
为4
,因此评估4 * 5
并产生20
。x--
。收益率4
,将x
设置为3
。((--x) * 5) + x--;
。将20
添加到4
以产生24
。"3 vs 24"
。Java编程语言保证运算符的操作数似乎在特定的评估顺序中评估,即从左到右。
答案 1 :(得分:0)
操作数从左到右进行评估,您认为它是从右到左。所以--x设置为4然后--x * 5,即4 * 5为20.然后--x * 5 + x--使其成为24.最后x--被评估为3。
来自Java Docs:
Java编程语言保证了操作数 运算符似乎在特定的评估顺序中进行评估, 即从左到右。
以下是Java优先级的 good detailed article 。
答案 2 :(得分:0)
因此,Java编译器找到了这个表达式:
int x = 5;
int y = --x * 5 + x--;
并且必须决定生成字节码的操作顺序。连续有四个运算符: - ,*,+和 - ,而不是单个括号,所以好的编译器会检查它的优先级表,并把你懒惰的程序员省略的括号:
((--OP1) * OP2) + (OP3--)
请注意,在这个阶段,操作数是不透明的实体:如果它们是变量(意味着从内存中读取),常量,方法调用,隐式取消装置或其他任何内容,那么它们并不重要 - 括号过程没有&#39我需要知道。
最后,当发出字节码时,编译器还有另一条要遵守的规则:操作数必须从左到右进行计算,以便从内存中读取和写入的操作(例如,变量递减/递增和方法调用)具有保证订单。因此,必须按照说明的顺序进行:
OP1
...
OP2
...
OP3
让我们使用IntegerVariable
进行面向对象,以查看更直观的示例:
public class IntegerVariable {
private int val;
public IntegerVariable(int val) {
this.val = val;
}
public int getAndDecrement() {
return val--;
}
public int decrementAndGet() {
return --val;
}
public int get() {
return val;
}
public static IntegerVariable Int(int val) {
return new IntegerVariable(val);
}
public static void main(String... args) {
IntegerVariable x = Int(5);
int y = x.decrementAndGet() * Int(5).get() + x.getAndDecrement();
}
}
如果您在get()
,decrementAndGet()
和getAndDecrement()
设置断点,则可以清楚地看到
y = ((--x) * 5) + (x--)
答案 3 :(得分:0)
运算符优先级与求值操作数的顺序无关。操作数始终从左到右进行评估。
运算符优先级确定如何计算表达式。例如,表达式4 * 5 + 6
可能意味着(4 * 5) + 6
或4 * (5 + 6)
。因为*
具有更高的运算符优先级,所以正确的优先级是第一个。
前缀和后缀递减和递增都具有较高的运算符优先级,因此--x * 5
表示(--x) * 5
而不是--(x * 5)
。显然,后一个表达式会产生编译器错误,因为x * 5
不是变量。这就是前缀和后缀递减和递增具有高运算符优先级的原因:将--x * 5
评估为--(x * 5)
是没有意义的。
因此,在您的情况下,表达式等同于((--x) * 5) + (x--)
。然后可以评估此表达式,其中严格地从左到右评估操作数。
答案 4 :(得分:-1)
x--在指令执行后发生。 所以就像4 * 5 + 4;并且在执行该语句之后,x再次递减为3。
这就是为什么3和24