首先,书上说的都是右结合性,甚至JLS中也明确的说了“The conditional operator is syntactically right-associative (it groups right-to-left). Thus, a?b:c?d:e?f:g means the same as a?b:(c?d:(e?f:g)).”
但是,如果是右结合性,有什么办法证明吗?我试着写了如下代码,却发现结果似乎在向我诉说三目运算符是左结合性的
String s = "abc";
int y = 1;
System.out.println("abc".equals(s) ? 1 : (++y) == 2 ? 0 : -1);
System.out.println(y);//1
如果是自右向左的结合性,那么(++y) == 2 ? 0 : -1 应该先被执行,也就是说y的值应该是2。但结果确是1……
我理解的结合性就是指在优先级相同的情况下,看是从左向右还是右向左。
自问自答吧。
stackoverflow上找到一种解释,我觉得还蛮不错。
就用a?b:c?d:e来说。
如果是左结合性,那么表达式等值于下((a?b:c)?d:e)。
于是乎变成了用(a?b:c)的结果,去决定究竟是返回d或者e。也就是说这个表达式只可能返回d或者e。这显然是不正确的。
三目运算符是自右向左的结合性的把
三目运算符被短路,这不能证明左结合
System.out.println("abc".equals(s) ? 1 : ((++y) == 2 ? 0 : -1));
这么写,肯定右结合,但是因为第一个条件是ture,导致((++y) == 2 ? 0 : -1)可以不被求值。
官方文档有明确说法,右结合就不用怀疑了。
运算符的结合性,是指表达式如何解析,
因为右结合性,所以
a ? b : c ? d : e 将被解析为 a ? b : ( c ? d : e )
也就是说后面的括号有没有都可以。
但并不影响表达式的求值。详细说明如下:
"abc".equals(s) ? 1 : (++y) == 2 ? 0 : -1
对应if/else写法如下:
if ( "abc".equals(s) ) {
return 1; //此时,整个表达式求值已经完毕,返回为1。
} else {
if ( (++y) == 2 ) {
return 0;
} else {
return -1;
}
}
如果你将题目中换成
"abcd".equals(s) ? 1 : (++y) == 2 ? 0 : -1)
再观察结果,就会有更深的体会。
楼上正解
System.out.println("abc".equals(s) ? 1 : ((++y) == 2 ? 0 : -1));后边的括号要不要都一样的。
建议你多试几次
String s = "abc";
int y = 1;
System.out.println("abc".equals(s) ? 1 : (++y) == 2 ? 0 : -1);//1
//因为"abc".equals(s)为true直接返回1,后边的不再执行所以第一句输出1
//此时y值为1
System.out.println(y);//1
还有,
String s = "ab";//只要不是abc就行
int y = 1;
System.out.println("abc".equals(s) ? 1 : (++y) == 2 ? 0 : -1);//0
//"abc".equals(s) 为false,执行 (++y) == 2 ? 0 : -1,由于(++y) == 2为true,返回0,所以输出0
//此时y值为2
System.out.println(y);//2
结合性,结合就一定要执行运算么?真是的!
打错了,更正下。。。
而文档上说的 a?b:c?d:e 等价 a?b:(c?d:e) 是用于和 (a?b:c)?d:e 进行的区分。两个三目运算符,优先级相同,优先级相同时,从右往左结合,前者是右结合,后者是左结合。
楼主,结合性说的是优先级相同时,从右往左结合,你看下边这段话:
f1() ? f2() : f3();
三个函数哪个先执行???显然f1是最先执行的,然后根据结果执行f2或者f3
而文档上说的 a?b:c?d:e 等价 a?b:(c?d:e) 是用于和 (a?b:c)?d:e 进行的区分。两个三目运算符,优先级相同,优先级相同时,从右往左结合,前者是左结合,后者是右结合。
扩展一下,会发现:
a?b:c?d:e?f:g的结合顺序有:((a?b:c)?d:e)?f:g、a?b:((c?d:e)?f:g)或a?b:(c?d:(e?f:g))三种结合方式,但是第三种才是从右向左的结合方式,也就是说,a?b:c?d:e?f:g默认的结合方式是第三种结合方式。但是表达式的执行顺序都是从左向右。
a?b:(c?d:(e?f:g))当a为true,返回b;当a为false,执行c?d:(e?f:g)
当c为true返回d;当c为false执行d:(e?f:g)。。。。。。类似于 f1() + f2() * f3(); 虽然乘号优先级比加号高 但是计算的时候 三个函数执行顺序还是 f1, f2, f3,就算你括号括起来 顺序也还是不变,运行自左向右。
总结:
结合----结合性----右结合性(优先级相同时,进行右结合)
运行----逻辑运算----从左向右