Почему тройной оператор неожиданно накладывает целые числа?

Я видел, как он обсуждался где-то, что следующий код приводит к тому, что obj является Double, но он печатает 200.0 с левой стороны.

Object obj = true ? new Integer(200) : new Double(0.0);

System.out.println(obj);

Результат: 200.0


Однако, если вы поместите другой объект в правую сторону, например, BigDecimal, тип obj равен Integer, как и должно быть.

Object obj = true ? new Integer(200) : new BigDecimal(0.0);

System.out.println(obj);

Результат: 200


Я предполагаю, что причина этого заключается в том, чтобы сместить левую сторону в Double так же, как это происходит для сравнений и вычислений Integer/Double, но здесь левая и правая стороны не взаимодействуют таким образом.

Почему это происходит?

Ответ 1

Вам необходимо прочитать раздел 15.25 Спецификации языка Java.

В частности:

В противном случае, если второй и третий операнды имеют типы, которые являются конвертируемыми (п. 5.1.8), к числовым типам, то есть несколько случаев:

  • Если один из операндов имеет тип байта или байт, а другой имеет тип short или Short, то тип условного выражения является коротким.
  • Если один из операндов имеет тип T, где T является байтом, коротким или char, а другой операнд является константным выражением типа int, значение которого представляется в типе T, то > - тип условное выражение - T.
  • Если один из операндов имеет тип Byte, а другой операнд является константным выражением типа int, значение которого представляется в байте типа, тогда тип условного выражения является байтом.
  • Если один из операндов имеет тип Short и другой операнд является константным выражением типа int, значение которого представляется в типе short, то тип условного выражения является коротким.
  • Если один из операндов имеет тип; Символ и другой операнд - это постоянное выражение типа int, значение которого представляется в типе char, тогда тип условного выражения char.
  • В противном случае для типов операндов применяется двоичное числовое продвижение (§5.6.2), а тип условного выражения - продвинутый тип второго и третьего операндов. Обратите внимание, что двоичное числовое продвижение выполняет преобразование для распаковки (§5.1.8) и преобразование значений (§5.1.13).

Итак, применяется двоичная цифровая реклама, которая начинается с:

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

  • Если какой-либо из операндов имеет ссылочный тип, выполняется преобразование распаковки (п. 5.1.8). Тогда:
  • Если один из операндов имеет тип double, другой преобразуется в double.

То, что здесь происходит - типы параметров преобразуются в int и double соответственно, второй операнд (третий в исходном выражении) имеет тип double, поэтому общий тип результата double.

Ответ 2

Числовое преобразование в условном операторе?

В условном операторе a ? b : c, если оба b и c являются разными числовыми типами, во время компиляции применяются следующие правила преобразования, чтобы сделать их типы равным, в порядке:

  • Типы преобразуются в соответствующие примитивные, которые называются unboxing.

  • Если один операнд был константой int (не Integer перед распаковкой), значение которой представляется в другом типе, операнд int преобразуется в другой тип.

  • В противном случае меньший тип преобразуется в следующий больший, пока оба операнда не будут иметь один и тот же тип. Заказы на конвертацию:
    byteshortintlongfloatdouble
    charintlongfloatdouble

В конечном итоге все условное выражение получает тип второго и третьего операндов.

Примеры:
Если вы объединяете char с short, выражение становится int.
Если вы объединяете Integer с Integer, выражение становится Integer.
Если вы объединяете final int i = 5 с Character, выражение становится char.
Если вы комбинируете short с float, выражение становится float.

В примере вопроса 200 преобразуется из Integer в double, 0.0 распаковывается из double в double, и все условное выражение становится double, которое в конечном итоге помещается в коробку в double, потому что obj имеет тип Object.