Почему мой символ печатается как число, а не символ?
согласно тернарному оператору 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, это описывает правила продвижения типа следующим образом:
когда оператор применяет двоичное числовое продвижение к паре операндов, каждый из которых должен обозначать значение, преобразуемое в числовой тип, применяются следующие правила:
если какой-либо операнд имеет тип ссылки, это подвергается распаковыванию преобразования (§5.1.8).
расширение примитивного преобразования (§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. Пишу