2013-05-27 9 views
10

Der folgende CodeGleichheitsvergleich von `boolean` und` Object` erlaubt?

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

mit javac ohne Fehler kompiliert V1.7.0_15 und druckt "false" bei der Ausführung. Eclipse Juno beschwert sich jedoch über "Inkompatible Operandentypen Object und boolean".

Offenbar Javac Autobox die primitiven boolean b, und vergleicht dann o und autoboxed b von Objekt Gleichheit, wodurch man false, während Eclipse-das Autoboxing tun will.

Welches ist das richtige Verhalten gemäß der Java Language Specification? Wo sollte ich einen Fehler ablegen?

Hinweis: Wenn ich die Art von o-Boolean ändern, die Dinge funktionieren wie erwartet: Eklipse den Code akzeptiert, und der Code druckt „true“.

Runnable version on ideone.com

+1

Überprüfen Sie die Eclipse-Einstellungen und sehen, ob es etwas flippig: Projekteigenschaften -> Java Compiler -> Fehler/Warnungen -> Mögliche Programmierung Probleme – blondeamon

+1

Hängt was Sie „erwartet“ - sollte es 'b' Box und Referenz Gleichheit verwenden (falsches Drucken) oder "o" auspacken und primitive boolesche Gleichheit verwenden (Druck wahr)? –

+0

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

Antwort

7

Es ist Ihr Projekt Sprachniveau Einstellung. Sie verwenden wahrscheinlich einen Java 7 Compiler mit Java 6 Semantik. Ich habe Eclipse hier nicht, aber ich reproduzierte es in IntelliJ, was Fehler gab, wenn das Sprachniveau auf Java 6 war, obwohl der Compiler, den ich verwendete, 7 war. Ich denke Eclipse hat das selbe. This link erklärt es.

+1

Dies scheint das Problem zu sein. Ich kann das Problem mit 'javac -source 1.6' reproduzieren, also scheint das Problem durch den Wechsel von 1.6 auf 1.7 verursacht worden zu sein. Eclipse zeigt jedoch den Fehler sogar für "Compiler Compliance Level = 1.7". Dies könnte ein Fehler im Eclipse-Compiler sein. – sleske

+0

@sleske Ich bestätige alles:/ – A4L

3

Bezüglich Ihrer 'Anmerkung', dass der Code kompiliert und funktioniert, wenn o-Boolean geändert wird:

Dieser Code:

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

produziert dieses Ergebnis:

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

Um zu sehen, warum Dies ist, müssen wir die Kompilierungszeit Arten der verschiedenen Ausdrücke betrachten:

  • one == two vergleicht eine Boolean mit einem Object - das sind die beiden Referenztypen, so ist der Test Gleichheit Referenz (Java Language Specification, Java SE 7 edition, §15.21.3)
  • one == three vergleicht eine Boolean mit einem boolean - dies ist als Vergleich der primitiven boolean Werte behandelt (§15.21.2); one ist ungepackt und mit three verglichen.
  • two == three vergleicht ein Object mit einem boolean - in diesem Fall die boolean zu Object durch einen Guss Umwandlung umgewandelt wird (§5.5, in diesem Fall Boxen boolean zu Boolean und dann Boolean zu Object Verbreiterung) und die beide werden dann zur Referenz Gleichheit verglichen .

Die EQUAL Linie ist viel einfacher - alle drei Fälle sind Anrufe zu Boolean.equals(Object other), mit Boxen, wenn das Argument three ist.

+0

Danke für die Klarstellung. Für 'two == three' sind daher sowohl ein Cast als auch Boxing/Unboxing notwendig, und Java wird zuerst autobox und dann cast. – sleske