Warum ist ein int-to-Object-Vergleich in Java 7 gültig, aber nicht in Java 8?

Lesezeit: 4 Minuten

Benutzer-Avatar
Matt_Bro

Der folgende Code,

private boolean compare(Object a, int b) {
    return a == b;
}

kompiliert in Java 7, führt aber in Java 8 zu folgendem Fehler:

unvergleichliche Typen: int und Object

Betrachtet man folgende Frage:

Vergleich von Object und int in Java 7

Es scheint, als ob Java 6 und Java 8 Sie nicht vergleichen lassen int und Object, während 7 tut. Gibt es dazu Unterlagen?

Mich interessiert das Hintergrundwissen, das diese Entscheidungen beeinflusst hat. Es scheint, als wären sie unentschlossen oder so.

Ich benutze IntelliJ-IDEE 14.1.4 mit JDK 1.7.0.51.

  • Wird der Fehler in Eclipse (dh bei Verwendung von ecj) oder vom JDK-Compiler angezeigt? Ich tippe auf einen Fehler in ecj…

    – Axel

    17. September 2015 um 14:09 Uhr

  • Wenn das der Fall ist, würde ich denken, dass Java 7 einen Fehler gemacht hat

    – Drache66

    17. September 2015 um 14:19 Uhr

  • Mit Java 7 von Oracle erhalte ich “Inkompatible Operandentypen: Objekt und int”. Stellen Sie den genauen Code bereit, den Sie beim Kompilieren in Java 7 beobachtet haben?

    – Andi Thomas

    17. September 2015 um 14:22 Uhr


  • @AndyThomas Ich denke, es hängt von der spezifischen Version des 1.7 jdk ab. llogiq konnte nicht mit jdk 1.7.0_75 kompiliert werden, während wir es mit jdk 1.7.0_71 kompilieren konnten. Vielleicht haben sie zwischen diesen Versionen einen Bugfix gemacht?

    – Irgendein JavaTyp

    17. September 2015 um 14:33 Uhr


  • Die Kompilierung schlägt auf jdk 1.7.0_67 fehl

    – Algiogie

    17. September 2015 um 14:50 Uhr

Benutzer-Avatar
wer

Java 7 wendet Autoboxing auf int an.

 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

Ich habe das mit erstellt build 1.7.0_71-b14

BEARBEITEN:

Dieses Verhalten wurde von Oracle als Fehler erkannt und behandelt:
JDK-8013357: Javac akzeptiert fehlerhafte binäre Vergleichsoperationen

Der relevante JLS-Abschnitt ist 15.21. Javac scheint dies als Referenzvergleich zu behandeln, aber ein Referenzvergleich ist nur zulässig, wenn BEIDE Operanden Referenztypen sind.


Die Typregeln für binäre Vergleiche in JLS-Abschnitt 15.21 werden jetzt korrekt von javac erzwungen. Seit JDK5, javac hat einige Programme mit Object-Primitive-Vergleichen akzeptiert, die gemäß JLS 15.21 falsch typisiert sind. Diese Vergleiche werden nun korrekt als Tippfehler erkannt.

Benutzer-Avatar
Maroun

Das JLS – Kapitel 15. Gleichheitsoperatoren erwähnt 3 verschiedene == Betreiber: numerisch, boolesch und Hinweis. Keiner des == Operatoren können in Ihrem Beispiel vorkommen, daher schließen wir daraus, dass die Anweisung ist illegal.

Mal sehen warum == kann in Ihrem Beispiel nicht angewendet werden:

  • 15.21.2. Boolesche Gleichheitsoperatoren == und !=

    Warum es nicht relevant ist, muss nicht erwähnt werden.

  • 15.21.3. Referenzgleichheitsoperatoren == und !=

    Wenn die Operanden eines Gleichheitsoperators beide entweder vom Referenztyp oder vom Nulltyp sind, handelt es sich bei der Operation um Objektgleichheit.

    Es ist ein Kompilierzeitfehler, wenn es unmöglich ist, den Typ eines Operanden durch eine Casting-Konvertierung in den Typ des anderen zu konvertieren (§5.5). Die Laufzeitwerte der beiden Operanden wären zwangsläufig ungleich.

  • 15.21.1. Numerische Gleichheitsoperatoren == und !=

    Wenn die Operanden eines Gleichheitsoperators beide vom numerischen Typ sind oder einer vom numerischen Typ und der andere konvertierbar ist (§5.1.8) in den numerischen Typ wird eine binäre numerische Hochstufung für die Operanden (§5.6.2).

Nehmen wir nun an, es ist legal und der Compiler hat die Zeile geändert in:

if (a == new Integer(b))

Was erwartest du als Ergebnis? Die Bedingung wird nie ausgewertet truealso macht es Sinn, dass es ist ein Fehler das wurde in Java 8 behoben.

  • Autoboxing wird jedoch mit durchgeführt Integer.valueOf. Seit Integer.valueOf gibt manchmal Werte aus einem Pool zurück, das Ergebnis könnte sein true.

    – Fabian

    17. September 2015 um 14:28 Uhr

  • @fabian Also, nie wahr in einer einigermaßen nützlichen oder intuitiven Weise.

    – Yakk – Adam Nevraumont

    17. September 2015 um 17:30 Uhr

  • @MarounMaroun Nun, für den Code in der Antwort wird es definitiv nie wahr sein. new Integer(b) erzeugt immer ein Objekt, wohingegen Integer.valueOf(b) möglicherweise nicht.

    – Benutzer253751

    18. September 2015 um 2:27 Uhr

  • Wie andere Kommentatoren gesagt haben, ist diese Antwort falsch. Der Vergleich einer Ganzzahl und eines Objekts ist mit Autoboxing gut definiert.

    – Navin

    18. September 2015 um 4:11 Uhr

Ich konnte weder mit javac 1.7.0_75 noch mit javac 1.8.0_60 ein Beispiel zum Kompilieren (Fixieren von bool → boolean) erhalten. Ich habe kein JDK6, aber ich denke auch nicht, dass es dort hätte funktionieren sollen. Vielleicht ist es eine frühere ecj-Inkompatibilität, wie Axel andeutet, oder ein Fehler in einer anderen Nebenversion von Javac.

Wenn es funktioniert, liegt es auf jeden Fall am Autoboxing. Dies wurde möglicherweise in Vorbereitung auf Java 8 zurückgefahren, da sich Streams und Autoboxing nicht so gut vertragen.

Benutzer-Avatar
Zhong Yu

Es hätte laut nicht kompiliert werden sollen JLS 7. int kann mit umrahmten numerischen Typen verglichen werden, dh Byte, Short, Character, Integer, Long, Float, Double. Aber das ist alles.

Und wenn Vergleich zwischen ist int und sag Float, Float wird zuerst ausgepackt, damit der Vergleich zwischen ist float und int. Es macht keinen Sinn, es andersherum zu machen – Box int prüfen Sie dann die Identität der Integer (mit einer Float nicht weniger).

1071650cookie-checkWarum ist ein int-to-Object-Vergleich in Java 7 gültig, aber nicht in Java 8?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy