Ich habe diesen Beitrag gelesen negative und positive Null .
Zu meinem Verständnis folgenden Code geben soll true
und true
als Ausgang.
Es ist jedoch zu geben false
und true
als Ausgang.
Ich vergleiche negativ Null mit einer positiven Null.
public class Test {
public static void main(String[] args) {
float f = 0;
float f2 = -f;
Float F = new Float(f);
Float F1 = new Float(f2);
System.out.println(F1.equals(F));
int i = 0;
int i2 = -i;
Integer I = new Integer(i);
Integer I1 = new Integer(i2);
System.out.println(I1.equals(I));
}
}
Warum haben wir ein anderes Verhalten für 0'en für Integer
und Float
?
Ints und Schwimmer sind ziemlich unterschiedliche Tiere in Java. Ints werden als codierte Zweier-Komplement , die einen einzelnen Wert 0 hat. Floats verwendet IEEE 754 (die 32-Bit - Variante für die Hin- und Herbewegungen, und 64-Bit - für doppelte). 754 IEEE ist etwas komplex, aber für Zwecke dieser Antwort, man muss nur wissen , dass es drei Abschnitte aufweist, von denen die erste ist ein Vorzeichenbit. Das bedeutet für jeden Schwimmer, gibt es eine positive und negative variant¹. Dazu gehört 0, so schwimmt tatsächlich zwei „Null“ Werte, +0 und -0.
Als beiseite, das Zweierkomplement dass Ints verwenden ist nicht die einzige Art und Weise zu kodieren ganzen Zahlen in der Informatik. Es gibt andere Methoden, wie einerkomplement , aber sie haben Macken - wie mit sowohl einer +0 und -0 als unterschiedliche Werte. ;-)
Wenn Sie Schwimmer Primitiven (und Doppel) vergleichen zu können , behandelt Java +0 und -0 als gleich. Aber wenn man sie boxen, Java behandelt sie getrennt, wie beschrieben Float#equals
. Auf diese Weise kann die Methode equals mit ihrer im Einklang hashCode
Implementierung (wie auch compareTo
), die nur die Bits des Schwimmers verwendet (einschließlich diesem Wert mit Vorzeichen) und schiebt sie wie sie ist in einen int.
Sie hätten eine andere Option für equals / hashCode / compareTo gepflückt, aber sie tat es nicht. Ich bin mir nicht sicher , was die Design - Überlegungen waren. Aber zumindest in einer Hinsicht, Float#equals
würde immer von dem Schwimmer primitiven dem abweichen ==
: In Primitiven NaN != NaN
, sondern für alle Objekte, o.equals(o)
auch wahr sein muss . Das bedeutet , dass , wenn Sie hatte Float f = Float.NaN
, dann , f.equals(f)
obwohl f.floatValue() != f.floatValue()
.
¹ NaN (not-a-number) Werte haben einen Vorzeichen-Bit, aber es hat keine andere Bedeutung als für die Bestellung, und Java ignoriert es (auch für die Bestellung).