Вопрос по conditional-operator, casting, java, ternary-operator – Почему троичный оператор неожиданно приводит целые числа?

40

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

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

Я не разбираюсь в Java, но правильный вопрос, который нужно задать, это "какой тип троичного условного выражения?" Kerrek SB
Должен признать, это довольно запутанный материал. Действительно удивил меня, когда я запустил это в NetBeans иobj.getClass() шоуDouble, Какого черта, чувак. G_H

Ваш Ответ

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

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

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

Если бы один операнд былпостоянная 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 вdouble0.0 распакован изDouble вdouble и все условное выражение становитсяdouble который в конечном итоге врезан вDouble потому чтоobj имеет типObject.

Цель этого ответа - выразить полное определение, включая распаковку, числовое продвижение и т. Д., С помощью нескольких простых правил, которые легко запомнить. Gerhard
34

раздел 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, другой преобразуется в двойной.

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

Гах Джон Скит победил меня в этом :) +1 Vivin Paliath
@HXCaine: Что бы вы хотели, чтобы это делалось в случае тех же типов, нопримитивный из них? Имейте в виду, что тип выражения отличается от части присваивания. Jon Skeet
Хотя я рад, что есть документация, я не вижу причины этого где-то там (но я уверен, что я не выгляжу должным образом). Мне кажется, что это задание и нет необходимости в продвижении двоичных чисел, я что-то упустил? HXCaine
@VivinPaliath Да, я тоже, но это нормально, потому что я собирался украсть его цитату из другого вопроса о троичном операторе, который у нас был некоторое время назад ;-) Voo
@ HXCaine: Да. Компилятор решает, что это за тип, а затем определяет, может ли он быть преобразован в целевое назначение. Обратите внимание, что вывод общего типа является одним из контрпримеров к этому, но это единственный, который я могу придумать не по порядку :) Jon Skeet
0

Пример:

    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.

}

Похожие вопросы