Java: странное поведение условного оператора - PullRequest
0 голосов
/ 28 мая 2020

У меня есть очень простой java класс для решения способов декодирования с использованием рекурсивного подхода. Я наблюдаю странное поведение условного оператора

package decodeways;

public class Solution {
  public static void main(String[] args) {
    System.out.println(numDecodings("1456"));
  }

  public static int numDecodings(String s) {
    if(s.length()>0 && s.charAt(0)=='0') 
      return 0;
    if(s.length()==0) return 1;
    if(s.length()==1)
      return 1;

    int num1 = s.charAt(0)-'0';
    int num2 = s.charAt(1)-'0';
    int one = numDecodings(s.substring(1));
    int two = s.length()>1?numDecodings(s.substring(2)):0;
    int res = one 
        + num1<3 && num2<7 ? two:0;
    return res;
  }
}

, если я поставлю круглые скобки (num1<3 && num2<7 ? two:0), тогда все будет хорошо, но если я уберу круглые скобки, то получаю неверные результаты.

в процессе отладки, one будет вычислено как 1, а two будет вычислено как 1, а res также будет 1 со скобками, но без В результате вычисленный результат res будет равен 0 (скриншот прилагается), что является источником ошибки. enter image description here Мне известно о приоритете оператора в java, но в этой ситуации я не могу понять, почему он показывает неправильное поведение, потому что в приведенном ниже коде:

int res = one 
        + num1<3 && num2<7 ? two:0;

one + num1 <3 недопустимо Итак, java достаточно умен, чтобы не путать между (one + num1 <3) и (num2 <7? Two: 0), чтобы рассматривать их отдельно. Итак, насколько я понимаю, единственное законное наблюдаемое поведение для java компилятора - это автоматически рассматривать <code>num1<3 && num2<7 ? two:0 как операцию atomi c (пожалуйста, поправьте меня, если я ошибаюсь), независимо от того, доступны ли скобки или нет.

Пожалуйста, помогите мне лучше понять.

Спасибо.

1 Ответ

5 голосов
/ 28 мая 2020
int res = one 
        + num1<3 && num2<7 ? two:0;

эквивалентно

int res = (((one + num1) < 3) && (num2 < 7)) ? two : 0;

Все, что до ?, включено в логическое выражение, поскольку тернарный / условный оператор имеет здесь самый низкий приоритет (не включая оператор присваивания) и + имеет наивысшее значение.

Порядок выглядит примерно так:

  • +, поэтому one + num1 складывается первым
  • <, поэтому теперь есть (one + num1) < 3 и num2 < 7
  • &&, после чего у вас есть ((one + num1) < 3) && (num2 < 7)
  • и наконец ?:

Похоже, вы ожидаете, что перевод строки заставит компилятор думать, что one и num1<3 && num2<7 ? two:0 разделены, но на самом деле он просто игнорирует все пробелы. Заключение круглых скобок - единственный способ убедиться, что one добавлено к тому, что оценивает условный оператор.

int res = one + (num1 < 3 && num2 < 7 ? two : 0);
...