Почему сопоставление int-to-Object справедливо в Java 7, но не в Java 8?

Следующий код

private boolean compare(Object a, int b) {
    return a == b;
}

компилируется в Java 7, но это приводит к следующей ошибке в Java 8:

несравнимые типы: int и Object

Рассматривая следующий вопрос:

Сравнение объектов и int в Java 7

Кажется, что Java 6 и Java 8 не позволяют сравнивать int и Object, в то время как 7. Есть ли какие-либо документы по этому поводу?

Мне интересны знания, которые информировали эти решения. Похоже, они не определились или что-то в этом роде.

Я использую IntelliJ IDEA 14.1.4 с JDK 1.7.0.51.

Ответ 1

Java 7 применяет автобоксинг к int.

 private boolean compare(java.lang.Object, int);
   Code:
      0: aload_1
      1: iload_2
      2: invokestatic  #2       // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      5: if_acmpne     12
      8: iconst_1
      9: goto          13
     12: iconst_0
     13: ireturn

Я создал это с помощью build 1.7.0_71-b14

EDIT:

Это поведение было признано и рассматривается как ошибка Oracle:
JDK-8013357: Javac принимает ошибочные операции двоичного сравнения

Соответствующий раздел JLS - 15.21. Кажется, что Джавак рассматривает это как сравнение ссылок, но сравнение ссылок разрешено только тогда, когда Оба операнда являются ссылочными типами.
...
Правила типа для бинарных сравнений в JLS Section 15.21 теперь будут правильно исполняемый javac. Поскольку JDK5, javac принял некоторые программы с примитивными сравнениями объектов, которые неправильно введены согласно JLS 15.21. Теперь эти сравнения будут правильно идентифицированные как ошибки типа.

Ответ 2

JLS - Глава 15. Операторы равенства упоминает 3 разных оператора ==: числовые, логические и ссылочные. Нет операторов == может произойти в вашем примере, поэтому мы заключаем, что оператор является незаконным.

Посмотрим, почему == не может быть применено в вашем примере:

  • 15.21.2. Операторы логического равенства == и!=

    Не нужно упоминать, почему это не актуально.

  • 15.21.3. Равенство ссылок Операторы == и!=

    Если операнды оператора равенства являются либо ссылочным типом, либо нулевым типом, то операция является равенством объекта.

    Это ошибка времени компиляции, если невозможно преобразовать тип любого операнда в тип другого путем преобразования кастования (§5.5). Значения времени выполнения двух операндов обязательно были бы неравными.

  • 15.21.1. Операторы числового равенства == и!=

    Если операнды оператора равенства имеют числовой тип, или один из числа, а другой является конвертируемым (§5.1.8) до числового типа, двоичная цифровая продвижение выполняется по операндам (§5.6.2).

Теперь предположим, что это законно, и компилятор изменил строку на:

if (a == new Integer(b))

Что вы ожидаете от результата? Условие никогда не будет оцениваться до true, поэтому имеет смысл, что это ошибка, которая была исправлена ​​в Java 8.

Ответ 3

Я не смог получить пример для компиляции (исправление bool → boolean) с помощью javac 1.7.0_75 или с javac 1.8.0_60. У меня нет JDK6, но я не думаю, что он тоже должен был там работать. Возможно, это более ранняя несовместимость ecj, как подсказывает Axel, или ошибка в другой младшей версии javac.

В любом случае, если он работает, это связано с автобоксированием. Возможно, это было исправлено при подготовке к Java 8, потому что потоки и автобоксинг не слишком хорошо смешиваются.

Ответ 4

Он не должен компилироваться, согласно JLS 7. int можно сравнить с числовыми типами в ящике, то есть байтом, коротким, символом, целым, длинным, плавающим, двойным. Но это все.

И если сравнение между int и say Float, Float будет сначала распаковано, так что сравнение будет между Float и int. Нет смысла делать обратное - box int, затем проверить личность IntegerFloat не менее).