guangzhanzb
guangzhanzb
采纳率66.7%
2017-04-26 14:45 阅读 1.9k
已采纳

Java中三目运算符结合性究竟是什么?

首先,书上说的都是右结合性,甚至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。这显然是不正确的。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

7条回答 默认 最新

  • 已采纳
    ljheee ljheee 2017-04-26 15:27

    三目运算符是自右向左的结合性的把

    点赞 评论 复制链接分享
  • fight_in_dl 战在春秋 2017-04-26 22:06

    官方文档有明确说法,右结合就不用怀疑了。
    运算符的结合性,是指表达式如何解析,
    因为右结合性,所以

     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)
    

    再观察结果,就会有更深的体会。

    点赞 1 评论 复制链接分享
  • qq_30718113 元_帅 2017-04-27 15:29

    楼主,结合性说的是优先级相同时,从右往左结合,你看下边这段话:

    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,就算你括号括起来 顺序也还是不变,运行自左向右。

    总结:
    结合----结合性----右结合性(优先级相同时,进行右结合)
    运行----逻辑运算----从左向右

    点赞 1 评论 复制链接分享
  • caozhy 从今以后生命中的每一秒都属于我爱的人 2017-04-26 15:49

    三目运算符被短路,这不能证明左结合

    System.out.println("abc".equals(s) ? 1 : ((++y) == 2 ? 0 : -1));
    这么写,肯定右结合,但是因为第一个条件是ture,导致((++y) == 2 ? 0 : -1)可以不被求值。

    点赞 评论 复制链接分享
  • qq_30718113 元_帅 2017-04-27 00:09

    楼上正解

    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
    
    点赞 评论 复制链接分享
  • qq_36539304 接口的说法 2017-04-27 02:06

    结合性,结合就一定要执行运算么?真是的!

    点赞 评论 复制链接分享
  • qq_30718113 元_帅 2017-04-27 15:27

    打错了,更正下。。。

    而文档上说的 a?b:c?d:e 等价 a?b:(c?d:e) 是用于和 (a?b:c)?d:e 进行的区分。两个三目运算符,优先级相同,优先级相同时,从右往左结合,前者是右结合,后者是左结合。

    点赞 评论 复制链接分享

相关推荐