Можно ли сравнить равенство `boolean` и` Object`?
Следующий код
public class TestComparison {
public static void main(String[] args) throws Exception {
boolean b = true;
Object o = new Boolean(true);
System.out.println("comparison result: "+
(o == b)); // Eclipse complains about this expression
}
}
компилируется без ошибок с javac
V1.7.0_15 и печатает "false" при запуске. Тем не менее, Eclipse Juno жалуется на "Несовместимые типы операндов Object и boolean".
Очевидно, javac autoboxes примитивный логический b
, а затем сравнивает o
и autoboxed b
по равенству объекта, давая false
, в то время как Eclipse отказывается делать автобоксинг.
Какое правильное поведение соответствует спецификации языка Java? Где я должен указать ошибку?
Примечание. Если я изменяю тип o
на Boolean
, все работает так, как ожидалось: Eclipse принимает код, а код печатает "true".
Runnable version на ideone.com
Ответы
Ответ 1
Это ваш уровень языкового уровня вашего проекта. Вероятно, вы используете компилятор Java 7 с семантикой Java 6. У меня нет Eclipse здесь, но я воспроизвел его в IntelliJ, который дал ошибки, когда языковой уровень был на Java 6, хотя я использовал компилятор 7. Я думаю, что Eclipse имеет то же самое. Эта ссылка объясняет это.
Ответ 2
Относительно вашего "примечания", что код компилируется и работает, когда o
изменен на Boolean
:
Этот код:
public class Tester{
public static void main(String args[]){
Boolean one = new Boolean(true);
Object two = new Boolean(true);
boolean three = true;
System.out.println("SAME 1:2 " + (one == two) + " 1:3 " + (one == three) + " 2:3 " + (two == three));
System.out.println("EQUAL 1:2 " + (one.equals(two)) + " 1:3 " + (one.equals(three)) + " 2:3 " + (two.equals(three)));
}
}
производит этот результат:
SAME 1:2 false 1:3 true 2:3 false
EQUAL 1:2 true 1:3 true 2:3 true
Чтобы понять, почему это так, нам нужно рассмотреть типы времени компиляции различных выражений:
-
one == two
сравнивает Boolean
с Object
- это оба ссылочных типа, поэтому тест является ссылочным равенством (Спецификация Java Language, Java SE 7 edition, §15.21.3)
-
one == three
сравнивает a Boolean
с Boolean
- это рассматривается как сравнение примитивных значений Boolean
(§15.21.2); one
распаковывается и сравнивается с three
.
-
two == three
сравнивает Object
с Boolean
- в этом случае Boolean
преобразуется в Object
с помощью преобразования каста (§5.5, в этом случае бокс Boolean
до Boolean
, а затем расширение Boolean
до Object
), а затем два сравниваются для ссылочного равенства.
Строка EQUAL
намного проще - все три случая являются вызовами Boolean.equals(Object other)
, используя бокс, когда аргумент three
.