Ints y flotantes son bestias bastante diferentes en Java. Los Ints se codifican como complemento de dos , que tiene un solo valor 0. Los flotantes usan IEEE 754 (la variante de 32 bits para flotantes y 64 bits para dobles). IEEE 754 es algo complejo, pero para el propósito de esta respuesta, solo necesita saber que tiene tres secciones, la primera de las cuales es un bit de signo. Eso significa que para cualquier flotador, hay una variante positiva y negativa¹. Eso incluye 0, por lo que los flotadores en realidad tienen dos valores "cero", +0 y -0.
Por otro lado, el complemento de dos que usa ints no es la única forma de codificar enteros en informática. Existen otros métodos, como el complemento de uno , pero tienen peculiaridades, como tener un +0 y -0 como valores distintos. ;-)
Cuando compara primitivas flotantes (y dobles), Java trata a +0 y -0 como iguales. Pero cuando los encajona, Java los trata por separado, como se describe en Float#equals
. Esto permite que el método equals sea coherente con su hashCode
implementación (así como también compareTo
), que solo usa los bits del flotante (incluido ese valor con signo) y los inserta tal cual en un int.
Podrían haber elegido alguna otra opción para equals / hashCode / compareTo, pero no lo hicieron. No estoy seguro de cuáles fueron las consideraciones de diseño. Pero al menos en un aspecto, Float#equals
siempre iba a divergir de los primitivos flotantes ==
: en primitivos NaN != NaN
, pero para todos los objetos, o.equals(o)
también debe ser cierto . Eso significa que si tuvieras Float f = Float.NaN
, f.equals(f)
aunquef.floatValue() != f.floatValue()
.
Values Los valores NaN (no un número) tienen un bit de signo, pero no tiene otro significado que no sea para ordenar, y Java lo ignora (incluso para ordenar).
i
yi2
son exactamente lo mismo Luego, cuando crea nuevosInteger
correos electrónicos, ambos envuelven exactamente el mismo valor.I1.equals(I)
será verdadint i = Integer.MIN_VALUE, i2 = -i;
...new
para los tipos de envoltura aquí. Solo use, por ejemploInteger i = 0, i2 = -i; System.out.println(i.equals(i2)); Float f1 = 0f, f2 = -f1; System.out.println(f1.equals(f2));