Почему мой символ печатается как число, а не символ?

согласно тернарному оператору Java expression ? statement1 : statement2, если expression истинно, то statement1 будет выполняться, если expression ложно, то statement2 будет выполнен.

но когда я запускаю:

// some unnecessary codes not displaying
char y = 'y';
int i = 0;
System.out.print(false ? i : y);

Я ожидаю, что он напечатает y но его печати 121, почему?

редактировать В соответствии с ответом manouti компилятор интерпретирует как int, а если это так, то почему я вижу мертвых код i?

если я это сделаю System.out.print(false ? 0 : x); тогда я получаю y, так почему же в этом случае компилятор не интерпретирует как int?

3 ответов


короткий ответ на ваш вопрос заключается в том, что напечатанное значение основано на типе, который вычисляет условное выражение.

так что на самом деле ваш вопрос сводится к тому, почему тип условного выражения отличается между

char y = 'y';
int i = 0;
System.out.print(false ? i : y); // prints 121

и

char y = 'y';
System.out.print(false ? 0 : y); // prints y

чтобы ответить на этот вопрос, нам нужно взглянуть на раздел §15.25 спецификации языка Java.

существует три типа условных выражения в Java:

  • Логические Условные Выражения
  • Числовые Условные Выражения
  • Условные Выражения Ссылки

так как int и char преобразуются в числовой тип, выражение является примером числовые условное выражение согласно этому правилу:

если второе и третье выражения операнда являются числовыми выражениями, то условное выражение-это числовое выражение.

С целью классификации условного, следующие выражения являются числовыми выражениями:

  • выражение автономной формы (§15.2) с типом, который преобразуется в числовой тип (§4.2, §5.1.8).

учитывая это, правило для определения типа всего выражения дается следующим образом:

15.25.2. Числовые Условные Выражения

числовые условные выражения являются отдельными выражениями (§15.2).

тип числового условного выражения определяется следующим образом:

  • если второй и третий операнды имеют одинаковый тип, тогда тип условного выражения.

  • если один из второго и третьего операндов имеет примитивный тип T, а тип другого-результат применения преобразования бокса (§5.1.7) к T, тогда тип условного выражения-T.

  • если один из операндов имеет тип byte или Byte, а другой-тип short или Short, то тип условного выражения short.

  • если один из операндов имеет тип T, где T-байт, short или char, а другой операнд является постоянным выражением (§15.28) типа int чье значение представляется в типе T, то тип условного выражения-T.

  • если один из операндов имеет тип T, где T-байт, короткий или символ, а другой операнд является постоянным выражением типа int, значение которого можно представить в типе U, который является результатом применения распаковки преобразования в T, то тип условного выражения-U.

  • в противном случае, двоичное числовое продвижение (§5.6.2) является применяется к типам операндов, а тип условного выражения является повышенным типом второго и третьего операндов.

отметьте, что двоичное числовое продвижение выполняет преобразование набора значений (§5.1.13) и может выполнять распаковыванию преобразования (§5.1.8).

обратите внимание, что четвертое правило точно описывает второй пример; второй операнд-это константа типа int (0) и третий -char, Так что условное выражение будет оцениваться как char. Это заставит компилятор использовать print(char) метод, который будет печатать y.

однако, когда вы вместо этого проходите в переменная вместо постоянный, вы падаете до последнего правила, которое говорит, что "...тип условного выражения является повышенным типом второго и третьего операндов."

если вы посмотрите на раздел §5.6.2 JLS, это описывает правила продвижения типа следующим образом:

когда оператор применяет двоичное числовое продвижение к паре операндов, каждый из которых должен обозначать значение, преобразуемое в числовой тип, применяются следующие правила:

  1. если какой-либо операнд имеет тип ссылки, это подвергается распаковыванию преобразования (§5.1.8).

  2. расширение примитивного преобразования (§5.1.2) применяется для преобразования либо оба операнда, как указано в следующих правилах:

    • если один из операндов имеет тип double, другой преобразуется в double.

    • в противном случае, если один из операндов имеет тип float, другой преобразуется в float.

    • в противном случае, если один из операндов имеет тип long, другой преобразуется в long.

    • в противном случае оба операнда преобразуются в тип int.

следуя этим правилам, тип выражения будет int, и поэтому компилятор будет использовать print(int) метод, который будет печатать 121 (значение ascii y).


121 является целочисленным представлением символа y. Так как вы предоставили i как часть выражения компилятор интерпретирует его как вызов System.out.print(int) вместо System.out.print(char).

обратите внимание, что изменение к System.out.print(false ? (char)i : y); печать y.


121-код ASCII для y и как вы объявили Я как целое число, компилятор интерпретирует y как переменная int тоже. Таким образом, печать значения ASCII для y. Пишу