Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Java 12 try to convert the result of a switch to a number?

I agree that this code:

var y = switch (0) {     case 0 -> '0';     case 1 -> 0.0F;     case 2 -> 2L;     case 3 -> true;     default -> 4; }; System.out.println(y); System.out.println(((Object) y).getClass().getName()); 

returns this:

0 java.lang.Character 

But if you remove boolean:

var y = switch (0) {     case 0 -> '0';     case 1 -> 0.0F;     case 2 -> 2L;     default -> 4; }; System.out.println(y); System.out.println(((Object) y).getClass().getName()); 

returns this:

48.0 java.lang.Float 

I suppose this result is unexpected.

like image 294
Ilya Avatar asked Mar 22 '19 06:03

Ilya


People also ask

What is the purpose of switch in Java?

The switch case in java executes one statement from multiple ones. Thus, it is like an if-else-if ladder statement. It works with a lot of data types. The switch statement is used to test the equality of a variable against several values specified in the test cases.

How do you return a switch in Java?

You can also think of the -> as a return statement which returns a value from the switch expression, and thus breaks the execution of the switch expression. The Java switch expression also works with Java String values.

Which type of data is accepted by switch statement in Java?

A switch works with the byte , short , char , and int primitive data types.

What can be used instead of switch case in Java?

Depending on the context switch s can also sometimes be replaced by arrays or hashmaps.


Video Answer


1 Answers

According to the switch expression's JEP, a switch expression is a poly expression:

A switch expression is a poly expression; if the target type is known, this type is pushed down into each arm. The type of a switch expression is its target type, if known; if not, a standalone type is computed by combining the types of each case arm.

Because you don't have a target type, the expression is not checked to match any given type, which is expected.

You can verify this by replacing var with a type:

int y = switch (0) {     case 0 -> '0';     case 1 -> 0.0F;     case 2 -> 2L;     case 3 -> true;     default -> 4; }; 

In my shell, this fails with:

|  Error: |  incompatible types: bad type in switch expression |      possible lossy conversion from float to int |      case 1 -> 0.0F; |                ^--^ |  Error: |  incompatible types: bad type in switch expression |      possible lossy conversion from long to int |      case 2 -> 2L; |                ^^ |  Error: |  incompatible types: bad type in switch expression |      boolean cannot be converted to int |      case 3 -> true; |                ^--^ 

But if you remove boolean:...

It should be enough to see how the standalone type is determined (rules here):

The type of a standalone switch expression is determined as follows:

  • If the result expressions all have the same type (which may be the null type), then that is the type of the switch expression.

  • Otherwise, if the type of each result expression is boolean or Boolean, an unboxing conversion (5.1.8) is applied to each result expression of type Boolean, and the switch expression has type boolean.

  • Otherwise, if the type of each result expression is convertible to a numeric type (5.1.8), the type of the switch expression is the result of numeric promotion (5.6) applied to the result expressions.

  • Otherwise, boxing conversion (5.1.7) is applied to each result expression that has a primitive type, after which the type of the switch expression is the result of applying capture conversion (5.1.10) to the least upper bound (4.10.4) of the types of the result expressions.

As far as I can see, when you remove the boolean expression, you're left with numeric expressions (char '0' (int 48) is promoted to float 48.0). See third bullet point above.

And as for why float is the result's type, see the Numeric Contexts section.

like image 131
ernest_k Avatar answered Oct 20 '22 01:10

ernest_k