Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有条件运算符和赋值运算符的表达式_Java_Javascript_Syntax_Operator Precedence - Fatal编程技术网

Java 具有条件运算符和赋值运算符的表达式

Java 具有条件运算符和赋值运算符的表达式,java,javascript,syntax,operator-precedence,Java,Javascript,Syntax,Operator Precedence,此Javascript表达式在所有浏览器中都能正常工作(): 现在是2点 但是为什么呢?我希望这里有一个例外,因为赋值的左侧是false?1:x,它不是有效的引用。与()比较: 这一个正在抛出一个ReferenceError。我仔细检查了,它表明条件运算符?:的优先级高于赋值运算符=,因此这两个表达式应该相同,至少我认为是这样 在Java中,类似Javascript的语法和运算符优先级规则非常相似,上面的两个表达式都会导致编译时错误,这是完全有道理的 有人能解释一下这种差异吗?正如您在MDN中发

此Javascript表达式在所有浏览器中都能正常工作():

现在是2点

但是为什么呢?我希望这里有一个例外,因为赋值的左侧是
false?1:x
,它不是有效的引用。与()比较:

这一个正在抛出一个
ReferenceError
。我仔细检查了,它表明条件运算符
?:
的优先级高于赋值运算符
=
,因此这两个表达式应该相同,至少我认为是这样

在Java中,类似Javascript的语法和运算符优先级规则非常相似,上面的两个表达式都会导致编译时错误,这是完全有道理的


有人能解释一下这种差异吗?

正如您在MDN中发现的那样,
比赋值运算符的前导度更高,这意味着JS将您的语句解读为:

false ? 1 : (x = 2);
乍一看,这似乎是倒退,但它的意思是
需要三个操作数,而
右侧的部分是第三个操作数。由于
=
具有较低的优先级,
x=2
成为第三个操作数

警报显示
2
,因为赋值
x=2
x
变量设置为
2
,然后此(子)表达式的计算结果为
2

你的第二个版本:

(false ? 1 : x) = 2;
…给出一个引用错误,因为它首先执行
(false?1:x)
部分,该部分的计算结果与
x
相关联的值(
未定义
),它不会返回变量
x
本身
undefined=2
不起作用。

三元运算符(?)需要三个值:条件、if true和if false

在表达式中

false ? 1 : x = 2
编译器将false视为条件,1视为if true,x=2。自从优先于=尚未计算x=2。因为false本质上是false,所以x=2是返回的

当计算x=2时,返回2

这就是为什么你可以写作

x = y = 2
在本例中,x和y都设置为2

整个x=2被视为if-false操作数而不仅仅是x的原因是因为三元运算符将所有内容都带到:的右侧,如果它在范围内,则视为if-false

然而,当您使用括号时,您试图做的是将文本(无论x是什么)设置为2,从而导致错误


我无法回答为什么在javascript中它可以工作,而在java中却会导致错误的问题。我只能假设操作员优先级略有不同

以下是理解JavaScript条件表达式和Java条件表达式之间差异的两个关键点:

1
请阅读ECMAScript 5注释规范本节底部的注释:

现在,请阅读Java规范部分中的条件表达式:

1

您将注意到,正如ECMAScript 5注释所述,Java中三元运算符中的第三个操作数不能只是任何旧表达式—它只能是一个条件表达式。但是,对于ECMAScript 5,第三个操作数可以是任何AssignmentExpression

进一步查看Java规范,我们发现表达式是任何赋值表达式:

1

但是ConditionalExpression要么是带有三元运算符(…?…:…)的ConditionalExpression,要么只是一个ConditionalRexpression(在ES5中称为LogicalRexpression)(有关该信息,请参见上面的前两个链接之一)。ConditionalOrExpression的“链”可以从Java中的此处开始:

在ECMAScript 5中:

在ECMAScript 5规范中,从ConditionalExpression到基本上每一个其他表达式,在表达式类型的“链”的后面(因为它比Java规范更容易遵循),但赋值表达式最终在一开始就到达了我们的位置-主表达式:

1

上面两个代码段中的第二个操作数都是主表达式:

1
所有这些繁琐的操作(如果我没有记错的话)的结果是,在Java中,三元运算符的第三个操作数不能是赋值,但在JavaScript中可以。这就是为什么两个示例在Java中都失败了,但在JavaScript中只有第二个失败

为什么第一个可以在JavaScript中工作,而第二个不能

operand1 ? operand2 : operand3;
其工作原理与以下代码类似(实际上并非如此,但下面的代码说明了上述代码的工作原理):

因此:

变成(同样,不是实际上-下面的代码是上述代码的示例):

但是,在第二个代码段中,当使用paren时,将条件表达式与“=2;”显式分开:

变成(同样,不是实际上-下面的代码是上述代码的示例):

三元运算符的“行为类似于示例IIFE函数调用”行为将返回任何x,该x将是一个值,而不是一个无法赋值的引用。因此出现了错误。这类似于以下代码(如果x==3):

显然,我们不能这样做

我认为,在Java中,第一个运算符给出错误是因为第三个运算符不能赋值,第二个运算符给出错误是因为不能赋值(就像JavaScript中一样)

关于运算符优先级,请查看以下代码:

var x = 3;

console.log(false ? 1 : x);          // ?: evaluates to "3"
console.log(false ? 1 : x = 2);      // ?: evaluates to "2"
console.log(false ? 1 : x = 2, 4);   // ?: evaluates to "2" - "2" and "4" arguments passed to log
console.log((false ? 1 : x = 2, 4)); // ?: evaluates to "4"
console.log((false ? 1 : x = 2), 4);
前两个在上面的IIFE说明性代码中很容易理解

第一行计算x,条件表达式计算为3,这很简单

在第二行中,我能描述它的最好方式是,条件运算符(?:)甚至会导致较低优先级的“=”运算符作为一个完整表达式进行计算,这不是因为(?:)具有较高的优先级,而是因为规范声明了以下赋值表达式:
(function () { if (false) return 1; else return x;}()) = 2;
3 = 2;
var x = 3;

console.log(false ? 1 : x);          // ?: evaluates to "3"
console.log(false ? 1 : x = 2);      // ?: evaluates to "2"
console.log(false ? 1 : x = 2, 4);   // ?: evaluates to "2" - "2" and "4" arguments passed to log
console.log((false ? 1 : x = 2, 4)); // ?: evaluates to "4"
console.log((false ? 1 : x = 2), 4);