Why is my char printing as a number instead of a character?

4.5k views Asked by At

As per the Java ternary operator expression ? statement1 : statement2, if expression is true then statement1 will be executed, if expression is false then statement2 will be executed.

But when I run:

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

I am expecting it to print y but its printing 121, why?

EDIT As per the manouti answer, the compiler interprets as int, but if that is the case then why I am seeing dead code at i?

If I do System.out.print(false ? 0 : x); then I am getting y, so why in this case doesn't the compiler interpret as int?

3

There are 3 answers

3
azurefrog On BEST ANSWER

The short answer to your question is that the value printed is based on the type that the conditional expression evaluates to.

So really your question boils down to, why does the type of the conditional expression differ between

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

and

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

To answer that, we'll need to take a look at section §15.25 of the Java Language Specification.

There are three types of conditional expression in Java:

  • Boolean Conditional Expressions
  • Numeric Conditional Expressions
  • Reference Conditional Expressions

Since both int and char are convertible to a numeric type, the expression is an example of a numeric conditional expression according to this rule:

If both the second and the third operand expressions are numeric expressions, the conditional expression is a numeric conditional expression.

For the purpose of classifying a conditional, the following expressions are numeric expressions:

  • An expression of a standalone form (§15.2) with a type that is convertible to a numeric type (§4.2, §5.1.8).

Given that, the rule for determining the type of the entire expression is given as follows:

15.25.2. Numeric Conditional Expressions

Numeric conditional expressions are standalone expressions (§15.2).

The type of a numeric conditional expression is determined as follows:

  • If the second and third operands have the same type, then that is the type of the conditional expression.

  • If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

  • If one of the operands is of type byte or Byte and the other is of type short or Short, then the type of the conditional expression is short.

  • If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T.

  • If one of the operands is of type T, where T is Byte, Short, or Character, and the other operand is a constant expression of type int whose value is representable in the type U which is the result of applying unboxing conversion to T, then the type of the conditional expression is U.

  • Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.

Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).

Notice that the fourth rule exactly describes the second example; the second operand is constant of type int (0) and the third is a char, so the conditional expression will evaluate to char. This will cause the compiler to use the print(char) method, which will print y.

However when you instead pass in a variable instead of a constant, you fall down to the last rule which says that "...the type of the conditional expression is the promoted type of the second and third operands."

If you take a look at section §5.6.2 of the JLS, it describes the rules for type promotion as follows:

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

  1. If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).

  2. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

    • If either operand is of type double, the other is converted to double.

    • Otherwise, if either operand is of type float, the other is converted to float.

    • Otherwise, if either operand is of type long, the other is converted to long.

    • Otherwise, both operands are converted to type int.

By following these rules, the type of the expression will be int, and so the compiler will use the print(int) method, which will print 121 (the ascii value of y).

5
M A On

121 is the integer representation of the character y. Since you provided i as part of the expression, the compiler interprets it as a call to System.out.print(int) instead of System.out.print(char).

Note that changing to System.out.print(false ? (char)i : y); prints y.

0
Udit On

121 is ASCII code for y and as you have declared i as an integer, the compiler interprets y as int variable too. Thus printing an ASCII value for y. Writing System.out.print(false ? (char)i : y) will print y.