Почему сопоставление 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 разных оператора ==
: числовые, логические и ссылочные. Нет операторов ==
может произойти в вашем примере, поэтому мы заключаем, что оператор является незаконным.
Посмотрим, почему ==
не может быть применено в вашем примере:
Теперь предположим, что это законно, и компилятор изменил строку на:
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
, затем проверить личность Integer
(с Float
не менее).