2012-01-31 26 views
10

考虑这个功能:在Java中保证操作的从左到右顺序?

public static final int F(int a, int b) { 
    a = a - 1 + b; 
    // and some stuff 
    return a; 
} 

需要它的JVM中的实现执行- 1+ b过吗?

如果我们有一个系统分析器连接到JVM,我们会看到在+ 1操作之前执行了+ b操作吗?

+0

的全面优先看名单并不是说是相关的,但什么是'input'? – 2012-01-31 14:44:57

+0

@SoboLAN错字错误.. – Pacerier 2012-01-31 14:49:58

+1

@Pacerier - 这不是[Short,Self Contained,Correct(Compilable),Example](http://sscce.org)。它不是独立的(没有阶级分化,也不是主要的)。它不可编译(它包含一个错字 - 你是否复制并粘贴了这个?)。 – 2012-01-31 15:02:31

回答

6

其实,我会不同意其余的答案。人们提到的JLS§15.7讨论了操作数的评估。也就是说,在表达式

x = foo() - 1 + bar() 

,按顺序调用这些方法。

相关的部分是§15.7.3,指定

的实现可能不利用代数恒等式,如结合律改写成表达更方便的计算顺序除非它可以证明,替换表达式是等效于值,并在其可观察到的副作用 [...]

由于第表达式x = x - 1 + qx = x + q - 1在所有方面都是等价的,允许一致性实现重写表达式(如果出于某种原因应该认为它更有效)。

+0

@Pacerier,请注意以下事项。一般来说,'foo()'可以影响'bar()',因此JVM应该遵守这个顺序。 'i> 0 && x/i> 3'也一样。代数上,'a && b'相当于'b && a',但'i> 0'首先避免了第二个表达式中的NPE。 – rdllopes 2016-07-22 09:58:28

2

根据here:在同一行

运算符具有相同的优先级。当 等号优先级的运算符出现在同一个表达式中时,规则必须支配首先评估的 。除了 赋值操作符之外的所有二元运算符都从左到右进行求值;分配 运营商从右到左进行评估。

所以,是的。

2

是的,虽然更大的问题是真的吗?减法和加法在任何科学数学运算中都具有相同的优先级,并且是可交换的。即:

x = input - 1 + q;

相同

X =输入+ Q - 1;

+0

我的意思是,当它溢出时我不喜欢它,但即使它溢出,也会考虑它,结果是一样的。 – Pacerier 2012-01-31 14:52:57

+0

确实如此,但无论哪种方式,您都可能会发生溢出 - 即:如果输入是MIN_INTEGER或q + input = MAX_INTEGER。在你的例子中没有真正的方法来防止这种情况发生。 – 2012-01-31 15:03:59

1

是的,它总是会,即使它不会影响增加的结果/减去。

7

是的,它是在Java语言specification,§15.7。

Java编程语言保证运营商的操作数出现在一个特定的评估顺序进行评价,即,由左到右。

建议代码不要严格依赖于此规范。当每个表达式至多包含一个副作用时,代码通常会更清晰,作为其最外层操作,并且代码并不完全依赖于由表达式的左到右评估导致出现哪种异常。

+0

“似乎有待评估” - Java是否具有“as-if”规则,类似于C和C++标准?也就是说,只要JVM无法与标准的行为区别开来就可以做任何事情。 – 2012-01-31 15:06:06

+2

@Rob是的,它的确如此。它可以以执行线程*出现的任何顺序执行操作,就像它们按照指定顺序执行一样。然而,从其他线程的角度来看,它们可能看起来不合时宜。这就是为什么多个线程必须使用明确的内存屏障进行协调的原因 – erickson 2012-01-31 15:06:50

1

它实际上不是JVM实现的重要内容,因为它们只是执行类文件中的指令列表。

2

你可以在这里看到Java中的运算符优先级:http://bmanolov.free.fr/javaoperators.php。因为+-具有相同的优先级,它们将按它们出现的顺序执行。

如果你想成为什么,其操作首先发生更清晰(或者,如果你想打破内置的优先级),你可以(也应该)使用括号(()),像这样:

x = (a - b) + (c * (d - e))

1

在我看来,总是会有从执行 X + Q的副作用 - 1 当你要执行 X - 1个+ Q。

当总和X + q的值超过由Bignum的1,从左到右执行会成功...的乱序执行的将产生溢出。

所以乱序执行有副作用。

除非乱序执行陷阱溢出本身,然后重新做ES在必要时正确为了避免副作用的计算。

0

重要的是在这里补充的是,Java没有排队就行优先为运营商这似乎是基于操作的基本运算顺序。对于这个source

相关问题