Почему троичный оператор неожиданно приводит целые числа? - PullRequest
40 голосов
/ 04 ноября 2011

Я видел, как где-то обсуждалось, что следующий код приводит к 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сравнения и вычисления, но здесь левая и правая стороны не взаимодействуют таким образом.

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

Ответы [ 3 ]

34 голосов
/ 04 ноября 2011

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

В частности:

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

  • Если один из операндов имеет тип byte или Byte, а другой имеет тип short или Short, тогдатип условного выражения короткий.
  • Если один из операндов имеет тип T, где T - байт, короткий или символ, а другой операнд - константное выражение типа 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.

3 голосов
/ 16 марта 2017

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

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

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

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

  • В противном случае меньший тип преобразуется в следующий больший, пока оба операнда не имеют одинаковый тип. Заказы на конвертацию:
    byte -> short -> int -> long -> float -> double
    char -> int -> long -> float -> double

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

Примеры:
Если вы объедините 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.

0 голосов
/ 02 января 2019

Пример:

public static void main(String[] args) {
    int i = 10;
    int i2 = 10;
    long l = 100;
    byte b = 10;
    char c = 'A';
    Long result;
    // combine int with int result is int compiler error
   // result = true ? i : i2; // combine int with int, the expression becomes int
    //result = true ? b : c; // combine byte with char, the expression becomes int

    //combine int with long result will be long
    result = true ? l : i; // success - > combine long with int, the expression becomes long
    result = true ? i : l; // success - > combine int with long, the expression becomes long
    result = true ? b : l; // success - >  combine byte with long, the expression becomes long
    result = true ? c : l; // success - >  char long with long, the expression becomes long

    Integer intResult;
    intResult = true ? b : c; // combine char with byte, the expression becomes int.
   // intResult = true ? l : c; // fail combine long with char, the expression becomes long.

}
...