почему неожиданное поведение для условного оператора - PullRequest
1 голос
/ 18 января 2012

У меня есть фрагмент кода, подобный следующему

public class Test{
               public static void main(String[] args) {
                  System.out.println(true?false:true == true?false:true);
                                                -----------------------
               }
            }

Вывод false.Если вы используете Eclipse, вы получите волнистую (пунктирную) строку и предупреждение типа «Сравнение идентичных выражений».Обратите внимание на начало волнистой линии.

Я изменил код на следующий

              public class Test{
               public static void main(String[] args) {
                  System.out.println((true?false:true) == (true?false:true));
                                     ---------------------------------------
               }
            }

Вывод true.Если вы используете Eclipse, вы получите волнистую (пунктирную) строку и предупреждение типа «Сравнение идентичных выражений».Обратите внимание на начало волнистой линии.

Почему разница?

Ответы [ 4 ]

3 голосов
/ 18 января 2012

Поскольку троичный оператор (?:) имеет более низкий приоритет , чем оператор равенства (==).Это означает, что:

true?false:true == true?false:true

фактически интерпретируется как:

true?false:(true == true?false:true)

Это, в свою очередь, оценивается как:

true?false:((true == true)?false:true)

продолжение:

true?false:(true?false:true)

... и в конечном итоге:

true?false:(false)

и в конечном итоге:

true?false:false

И, очевидно, это объясняет вывод первого фрагмента кода.Eclipse правильно распознает приоритет оператора и выделяет, возможно, неверное утверждение.

ОБНОВЛЕНИЕ : Спасибо за все комментарии.На самом деле я забыл про приоритет оператора на левой стороне.Я проверил точное поведение, используя программу ниже:

public static boolean a(char label, boolean result) {
    System.out.println(label);
    return result;
}

public static void main(String[] args) {
    System.out.println(
        a('a', true) ? a('b', false) : a('c', true) == a('d', true) ? a('e', false) : a('f', true)
    );
}

Результаты соответствуют предложению @ Milad Naseri .

2 голосов
/ 18 января 2012

Здесь нет ничего неожиданного, ответ - приоритет оператора.В первом случае это:true?false:(true == true?false:true)В то время как во втором случае ваши паретезы имеют приоритет над правилами приоритета.

1 голос
/ 18 января 2012

В случае, если ваша проблема заключается в разнице результатов, это связано с порядком приоритета операторов, которые вы используете.Проверьте здесь для деталей.В соответствии с этим порядком приоритета:

true ? false : true == true ? false : true

такой же, как этот:

true ? false : ((true == true) ? false : true)

, поэтому он всегда будет иметь значение false .Вы можете поставить что-нибудь после двоеточия, так как оно никогда не вычисляется в любом случае (если я правильно помню, и троичный оператор использует ленивую оценку);причина этого в том, что

true ? A : B

всегда оценивается как A.


С другой стороны,

(true ? false : true) == (true ? false : true)

будет иметь обе стороны сравненияоператор == оценивать в ложь, поэтому

false == false

, что является true оператором.

Таким образом, здесь разница в том порядке, в котором оцениваются операторы, чтоопределяется используемыми вами круглыми скобками и, если есть неопределенность, которая не разрешается скобками, порядком приоритета используемых операторов.


В общем случае, троичный оператор "?: "работает следующим образом

A ? B : C

Если A истинно, вычислите значение B, в противном случае - значение C. A должно быть логическим выражением, B и C могут быть любыми значениями;вам придется иметь дело с несоответствиями типов, если вы хотите присвоить оцененное значение переменной, и они бывают разных типов.

1 голос
/ 18 января 2012

Это потому, что оператор условного равенства (==) имеет приоритет над троичным условным ?:. Таким образом, в a?b:x==y?z:t x==y?z:t оценивается до a?b:x и y?z:t.

...