2013-05-27 82 views
10

Poniższy kodRówne porównanie wartości `boolean` i` Object` dozwolone?

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 
    } 
} 

kompiluje bez błędów z javac V1.7.0_15 i drukuje "false" gdy bieg. Jednak Eclipse Juno narzeka na "Niezgodne typy operandów Object i boolean".

Widocznie javac autoboxes pierwotną logiczną b, a następnie porównuje o i autoboxed b o równości obiektu, otrzymując false, natomiast Eclipse odmawia zrobić autoboxing.

Jakie zachowanie jest właściwe zgodnie ze specyfikacją języka Java? Gdzie powinienem zgłosić błąd?

Uwaga: Jeśli zmienić typ o do Boolean, wszystko działa zgodnie z oczekiwaniami: Eclipse przyjmuje kod i drukuje kod „true”.

Runnable version on ideone.com

+1

Sprawdź ustawienia Eclipse i zobaczyć, czy jest tam coś Funky: Właściwości projektu -> Java Compiler -> Błędy/ostrzeżenia -> Potencjalne Programowanie Problemy – blondeamon

+1

Zależy czego „oczekiwany” - należy przez to pole 'B' i używać równości odniesienia (drukowanie fałszywe) lub unbox 'o' i użycie prymitywnej równości boolowskiej (drukowanie prawda)? –

+0

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

Odpowiedz

7

To twoje ustawienie poziomu język projektu. Prawdopodobnie używasz kompilatora Java 7 z semantyką Java 6. Nie mam tutaj Eclipse, ale odtworzyłem go w IntelliJ, co dawało błędy, gdy poziom języka był na Javie 6, mimo że użyłem kompilatora 7. Sądzę, że Eclipse ma to samo. This link to wyjaśnia.

+1

To wydaje się być problemem. Mogę odtworzyć problem za pomocą 'javac -source 1.6', więc wygląda na to, że problem spowodowany jest zmianą z 1.6 na 1.7. Jednak Eclipse pokazuje błąd nawet dla "Poziom zgodności kompilatora = 1,7". Może to być błąd w kompilatorze Eclipse. – sleske

+0

@sleske Potwierdzam to wszystko:/ – A4L

3

chodzi o swój 'Uwaga', że kod kompiluje i działa po o zmienia się na Boolean:

ten kod:

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))); 
    } 
} 

produkuje ten wynik:

SAME 1:2 false 1:3 true 2:3 false 
EQUAL 1:2 true 1:3 true 2:3 true 

zrozumieć, dlaczego to jest, musimy rozważyć kompilacji typy różnych wyrażeń:

  • one == two porównuje Boolean z Object - to obydwa rodzaje odniesienia, tak więc test jest równość odniesienia (Java Language Specification, Java SE 7 edition, §15.21.3)
  • one == three porównuje Boolean z boolean - jest traktowany jako porównanie pierwotnych boolean wartościami (§15.21.2); one jest rozpakowywany i porównywany z three.
  • two == three porównuje się Object z boolean - w tym przypadku boolean przekształca się Object poprzez konwersję odlewniczej (§5.5, w tym przypadku boksu boolean do Boolean i rozszerzającej Boolean do Object), a dwa są następnie porównywane równości referencyjnego .

Linia EQUAL jest znacznie prostsze - wszystkie trzy przypadki są rozmowy do Boolean.equals(Object other), wykorzystujące boks gdy argument jest three.

+0

Dzięki za wyjaśnienie. Tak więc dla 'dwóch == trzech', wymagane jest zarówno rzutowanie, jak i boksowanie/rozpakowywanie, a Java najpierw wykona autobox, a następnie rzuci. – sleske