Почему Java 12 пытается преобразовать результат переключения в число? - PullRequest
42 голосов
/ 22 марта 2019

Я согласен, что этот код:

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());

возвращает это:

0
java.lang.Character

Но если вы удалите логическое значение:

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());

вернет это:

48.0
java.lang.Float

Полагаю, этот результат неожиданный.

1 Ответ

47 голосов
/ 22 марта 2019

Согласно выражению-переключателю JEP , выражение-переключение является поли-выражением:

Выражение-переключатель - это поли-выражение; если тип цели известен, этот тип проталкивается вниз в каждую руку. Тип выражения switch - это его целевой тип, если он известен; если нет, то автономный тип вычисляется путем комбинирования типов руки каждого случая.

Поскольку у вас нет целевого типа, выражение не проверяется на соответствие какому-либо заданному типу, что ожидается.

Вы можете проверить это, заменив var на тип:

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

В моей оболочке это не с:

|  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;
|                ^--^

Но если вы удалите логическое значение: ...

Достаточно посмотреть, как определяется автономный тип ( правил здесь ):

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

  • Если все выражения результата имеют одинаковый тип (который может быть нулевым типом), то это тип выражения переключения.
  • В противном случае, если тип каждого результирующего выражения является логическим или логическим, преобразование распаковки (5.1.8) применяется к каждому результирующему выражению типа Boolean, а выражение коммутатора имеет тип логический.
  • В противном случае, если тип каждого выражения результата может быть преобразован в числовой тип (5.1.8), тип выражения переключения является результатом числового преобразования (5.6), примененного к выражениям результата.

  • В противном случае преобразование бокса (5.1.7) применяется к каждому результирующему выражению, имеющему примитивный тип, после чего тип выражения-переключателя является результатом применения преобразования захвата (5.1.10) к наименьшему верхняя граница (4.10.4) типов выражений результата.

Насколько я вижу, когда вы удаляете логическое выражение, у вас остаются числовые выражения (char '0' (int 48) повышается до float 48.0). См. Третий пункт выше.

А о том, почему float является типом результата, см. В разделе Числовой контекст .

...