2013-05-27 5 views
10

Следующий кодРазрешено сравнение равенства `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 и печатает «ложь» при запуске. Тем не менее, Eclipse Juno жалуется на «Несовместимые типы операндов Object и boolean».

Видимо JAVAC autoboxes примитивного булево b, а затем сравнивает o и autoboxed b объектного равенство, получая false, в то время как Eclipse, отказывается делать Autoboxing.

Какое правильное поведение соответствует спецификации языка Java? Где я должен регистрировать ошибку?

Примечание: Если изменить тип o к Boolean, все работает, как ожидалось: Затмение принимает код, и код выведет «истинный».

Runnable version on ideone.com

+1

Проверьте настройки Eclipse, и посмотреть, если есть что-то в стиле фанк: Свойства проекта -> Java Compiler -> Ошибки/предупреждения -> Потенциальный Программирование Проблемы – blondeamon

+1

Зависит то, что вы «ожидаемый» - она ​​должна поле 'b' и использовать равенство ссылок (печать false) или unbox 'o' и использование примитивного логического равенства (печать true)? –

+0

[java AutoBoxing rules] (http://jcp.org/aboutJava/communityprocess/jsr/tiger/autoboxing.html) –

ответ

7

Это ваша установка уровня языка проекта. Вероятно, вы используете компилятор Java 7 с семантикой Java 6. У меня нет Eclipse здесь, но я воспроизвел его в IntelliJ, который дал ошибки, когда языковой уровень был на Java 6, хотя я использовал компилятор 7. Я думаю, что Eclipse имеет то же самое. This link объясняет это.

+1

Кажется, это проблема. Я могу воспроизвести проблему с 'javac -source 1.6', поэтому проблема связана с изменением с 1.6 до 1.7. Однако Eclipse показывает ошибку даже для «уровня соответствия компилятора = 1.7». Это может быть ошибкой в ​​компиляторе Eclipse. – sleske

+0

@sleske Я подтверждаю все это:/ – A4L

3

Что касается вашего 'Примечание', что код компилируется и работает, когда 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 

Чтобы понять, почему это, мы должны рассмотреть compile-time типы различных выражений:

  • one == two сравнивает Boolean с Object - это как ссылочные типы, так что тест является ссылка равенство (Java Language Specification, Java SE 7 edition, §15.21.3)
  • one == three сравнивает 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.

+0

Спасибо за разъяснение. Так что для 'two == three' необходимы как бросок, так и бокс/распаковка, а Java будет сначала автобокс, а затем бросить. – sleske

Смежные вопросы