внутреннее выражение троичного оператора java + intellij вычисляют выражение - PullRequest
0 голосов
/ 30 мая 2018

Этот код будет выдавать NPE:

Integer wtf = false ? 1 : (Integer) null;

Дело в том, что если 2-й или 3-й операнд имеет тип int, то другой также будет преобразован в int.(согласно таблицам в этой части JLS https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25)

Мой первый вопрос: почему спецификация написана таким образом? Не имеет ли смысла преобразовывать значение в более выразительный параметр (Integer),чем к более примитивному (int)? Чтобы предотвратить этот вид чрезвычайно запутанных ошибок?

Второй вопрос, вы можете успешно оценить это выражение в выражении вычисления Intellij. Результатом будет объект wtf с назначенным нулем.ошибка или где-то указано, что она не совместима с JLS?

Ответы [ 2 ]

0 голосов
/ 30 мая 2018
  • Полагаю, причина была в эффективности и простоте: меньше памяти и прямой доступ вместо объекта-оболочки Integer .В противном случае, например, в Integer wtf = 40 + (false ? Integer.valueOf("1") : 2)); экземпляр Integer должен быть сгенерирован как промежуточный результат.
    Таблицы, на которые вы ссылаетесь, стали необходимыми упаковкой / распаковкой с Java 5В Java 1.4 не разрешалось использовать как int , так и Integer для второго и третьего операндов.
  • Да, это ошибка, потому что этонарушая JLS.
0 голосов
/ 30 мая 2018

почему спецификация написана таким образом?

Я не могу ответить почему , потому что я не написал спецификацию.Но я могу предложить причину, по которой не должно быть иначе.

Когда второй и третий параметры имеют разные типы, и оба типа могут быть преобразованы в числовые типы, они подвергаются двоичное числовое продвижение .Это то же самое, что и для других операторов, принимающих числовые операнды, например, +.

. Вы можете получить тот же NPE, если попытаетесь добавить int и Integer null:

System.out.println(1 + (Integer) null);

В этом случае вы не можете сделать что-нибудь полезное, поместив от 1 до Integer.valueOf(1).

Было бы непоследовательным, если бы числовые типы обрабатывались по-разному между операторами + и ?: (*).И условный оператор должен использовать некоторую форму двоичного числового преобразования, чтобы иметь возможность обрабатывать примитивные операнды различных типов, например, int и double.

Взгляд наспецификация для условного оператора должна убедить вас, что его обработка типов уже безумно сложна (см. таблицы с 15.25-A по E), и поэтому делать это не следует.

К сожалению, вы можете так выстрелить себе в ногу;но это только то, каков язык.

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


(*) На самом деле, это ведет себя немного по-другому.Например, (Integer) null + (Integer) null будет автоматически распакован, тогда как condition ? (Integer) null : (Integer) null будет не автоматически распакован.Эта разница возникает из-за того, что условный оператор указывает, что перед применением двоичного числового преобразования выполняется проверка для тех же типов операндов.

...