Vergleich der Long-Werte 127 und 128 in Kästchen


110

Ich möchte zwei Long- Objektwerte unter Verwendung von ifBedingungen vergleichen. Wenn diese Werte kleiner als 128 sind , iffunktioniert die Bedingung ordnungsgemäß. Wenn sie jedoch größer oder gleich 128 sind , schlägt der Vergleich fehl.

Beispiel:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

Der Vergleich mit dem obigen Code funktioniert ordnungsgemäß, schlägt jedoch im folgenden Code fehl:

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Warum gibt es ein Problem beim Vergleich von Long- Variablen mit Werten größer als 127 ? Wenn die Datentypen der Variablen in lange Grundelemente geändert werden, funktionieren die Vergleiche in allen Fällen.

Antworten:


212

TL; DR

Java zwischenspeichert Boxed Integer-Instanzen von -128bis 127. Da Sie verwenden ==Objekte vergleichen Referenzen statt Werte werden nur im Cache gespeicherten Objekte entsprechen. Arbeiten longSie entweder mit primitiven Werten ohne Box oder .equals()vergleichen Sie Ihre LongObjekte.

Lange (Wortspiel beabsichtigt) Version

Warum ist es problematisch, die Variable Long mit einem Wert größer als 127 zu vergleichen? Wenn der Datentyp der obigen Variablen primitiv (lang) ist, funktioniert der Code für alle Werte.

Java speichert Instanzen von Integer-Objekten im Bereich von -128 bis 127 zwischen . Das gesagt:

  • Wenn Sie den Wert 127( zwischengespeichert ) auf N Long-Variablen setzen , wird dieselbe Objektinstanz von allen Referenzen angezeigt. (N Variablen, 1 Instanz)
  • Wenn Sie den Wert 128( nicht zwischengespeichert ) auf N Long-Variablen setzen , wird von jeder Referenz eine Objektinstanz angezeigt. (N Variablen, N Instanzen)

Deshalb das:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

Gibt dies aus:

wahr
falsch falsch

Für den 127L- Wert wird zurückgegeben, da beide Referenzen (val1 und val2) auf dieselbe Objektinstanz im Speicher verweisen (zwischengespeichert) true.

Auf der anderen Seite wird für den 128- Wert, da keine Instanz für ihn im Speicher zwischengespeichert ist, eine neue für alle neuen Zuweisungen für Box-Werte erstellt, was zu zwei verschiedenen Instanzen führt (auf die durch val3 und val4 gezeigt wird) und falseauf den Wert zurückkehrt Vergleich zwischen ihnen.

Dies geschieht nur, weil Sie zwei Long Objektreferenzen und keine longprimitiven Werte mit dem ==Operator vergleichen. Ohne diesen Cache-Mechanismus würden diese Vergleiche immer fehlschlagen. Das eigentliche Problem hierbei ist also der Vergleich von Boxwerten mit dem ==Operator.

Das Ändern dieser Variablen in primitive longTypen verhindert dies. Wenn Sie Ihren Code jedoch mithilfe von LongObjekten beibehalten müssen, können Sie diese Vergleiche sicher mit den folgenden Ansätzen durchführen:

System.out.println(val3.equals(val4));                     // true
System.out.println(val3.longValue() == val4.longValue());  // true
System.out.println((long)val3 == (long)val4);              // true

(Eine ordnungsgemäße Nullprüfung ist auch für Gussteile erforderlich.)

IMO , es ist immer eine gute Idee, sich bei Objektvergleichen an die Methoden .equals () zu halten .

Referenzlinks:


15

Java speichert die primitiven Werte zwischen -128 und 127 zwischen . Wenn wir zwei Long- Objekte vergleichen, geben Sie Java intern in einen primitiven Wert ein und vergleichen Sie es. Aber über 127 erhält das Long-Objekt keine Typkaste. Java speichert die Ausgabe mit der Methode .valueOf () zwischen .

Dieses Caching funktioniert für Byte, Short, Long von -128 bis 127. Für Integer-Caching funktioniert Von -128 bis java.lang.Integer.IntegerCache.high oder 127, je nachdem, welcher Wert größer ist. (Wir können den Wert der obersten Ebene bis zu den Integer-Werten festlegen sollte mit java.lang.Integer.IntegerCache.high zwischengespeichert werden).

 For example:
    If we set java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

Float- und Double-Objekte werden niemals zwischengespeichert.

Der Charakter erhält einen Cache von 0 bis 127

Sie vergleichen zwei Objekte. Der Operator == prüft die Gleichheit der Objektreferenzen. Es gibt folgende Möglichkeiten.

1) Geben Sie cast beide Objekte in primitive Werte ein und vergleichen Sie

    (long)val3 == (long)val4

2) Wert des Objekts lesen und vergleichen

    val3.longValue() == val4.longValue()

3) Verwenden Sie beim Objektvergleich die Methode equals ().

    val3.equals(val4);  

14

num1und num2sind lange Objekte. Sie sollten verwenden equals(), um sie zu vergleichen. ==Der Vergleich funktioniert manchmal aufgrund der Art und Weise, wie JVM-Box-Grundelemente verwendet werden, hängt jedoch nicht davon ab.

if (num1.equals(num1))
{
 //code
}

1
Dies (was besser ist) oder vergleichen Sie den Rückgabewert von .longValue().
Giulio Franco

4

Beim Vergleich von Nicht-Grundelementen (auch als Objekte bezeichnet) in Java wird ==deren Referenz anstelle ihrer Werte verglichen. Longist eine Klasse und somit sind LongWerte Objekte.

Das Problem ist, dass die Java-Entwickler wollten , dass die Benutzer die Kompatibilität Longwie früher verwenden long, was zu dem Konzept des Autoboxing führte, bei dem es sich im Wesentlichen um die Funktion handelt, dass long-Werte nach Bedarf in Long-Objects geändert werden und umgekehrt. Das Verhalten von Autoboxen ist jedoch nicht immer genau vorhersehbar, da es nicht vollständig spezifiziert ist.

Um sicher zu gehen und vorhersehbare Ergebnisse zu erzielen, verwenden Sie immer .equals(), um Objekte zu vergleichen, und verlassen Sie sich in diesem Fall nicht auf Autoboxing:

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.