2012-09-01 32 views
11

Sé que Double es una clase de contenedor, y contiene el número double. Hoy, he visto otra diferencia principal:Java: diferentes dobles y dobles en comparación

double a = 1.0; 
double b = 1.0; 
Double c = 1.0; 
Double d = 1.0; 
System.out.println(a == b); // true 
System.out.println(c == d); // false 

So strange with me !!!

Por lo tanto, si utilizamos Double, cada vez, tenemos que hacer algo como esto:

private static final double delta = 0.0001; 
System.out.println(Math.abs(c-d) < delta); 

que no podemos explicar por qué Doble directamente Haga la comparación equivocada. Por favor explique por mi

gracias :)

+8

Use 'c.equals (d)' en lugar de '' ==. '==' solo verifica las referencias. – Baz

+2

@Baz Ah, lo entiendo. El doble es una clase. Comparará el objeto en lugar de comparar el valor. A este problema le gusta cuando lo hacemos con 'String'. debería usar 'igual' en lugar de' == ':) – hqt

+0

Sí, exactamente ... – Baz

Respuesta

21

c y d son técnicamente dos objetos diferentes y == operador compara sólo referencias.

c.equals(d) 

es mejor ya que compara valores, no referencias. Pero aún no es ideal. La comparación directa de los valores de punto flotante siempre debe tener en cuenta un error (épsilon) (Math.abs(c - d) < epsilon).

Tenga en cuenta que:

Integer c = 1; 
Integer d = 1; 

aquí comparación cedería true, pero eso es más complicado (Integer almacenamiento en caché interna, se describe en JavaDoc of Integer.valueOf()):

Este método siempre dará valores de caché en el rango - 128 a 127, inclusive, y puede almacenar en caché otros valores fuera de este rango.

¿Por qué valueOf()? Debido a que este método se utiliza implícitamente a implementar autoboxing:

Integer c = Integer.valueOf(1); 
Integer d = Integer.valueOf(1); 

Ver también

+0

Oh. Lo he entendido este problema le gusta cuando lo hacemos con la clase de cadena. Pero tu segundo ejemplo es interesante. ¿Puede decirme por qué es cierto cuando lo hago con un entero :) – hqt

+0

@hqt: echa un vistazo a los enlaces en * Ver también * sección de mi respuesta. –

+1

@hqt puede llamarlo grupo entero. Tamaño <-128,127> - Todos los enteros dentro de este rango son iguales usando ambos 'equals()' y '==' – dantuch

3

Uso equals() a los controles de la igualdad de los 2 objetos. == comprueba si las 2 referencias se refieren al mismo objeto en la memoria.

4

Cuando se aplica a las expresiones de un tipo de clase, == se siempre realizar una comparación de referencia (JLS section 15.21.3). Así que esta línea:

System.out.println(c == d); 

está comprobando si c y d se refiere a los mismos objetos. El auto-boxing en Java siempre (creo) crea un nuevo objeto para float y double (la situación es más complicada para los tipos integrales). Por lo tanto, c y d se refieren a objetos diferentes, por lo que imprime false.

Si desea comparar objetos para la igualdad, es necesario llamar explícitamente equals:

System.out.println(c.equals(d)); 

Con double, se trata de utilizar la igualdad numérica en lugar - como se especifica en section 15.21.1. De ahí la diferencia en el comportamiento.


Para autoboxing integral, los valores de "pequeños" se almacenan en caché - por lo autoboxing 5 (digamos) devolverá la misma referencia en todo momento. La definición de "pequeño" es específica de la implementación, pero está garantizada dentro del rango de -128 a 127. Consulte la parte inferior de section 5.1.7 para obtener más información.

+0

+1 grandes detalles! –

+1

Acerca de la memoria caché de enteros, ¿me puede decir por qué puede saber esto? No veo esto en ningún libro de Java que haya leído. (y no creo que aprendas todas las especificaciones de Java: D) – hqt

+0

@hqt Incluso si no sabes todas las especificaciones de memoria, después de un tiempo ya sabes la mayor parte. Y es una buena práctica que cada vez que vea algo que no sepa cómo funciona vaya y verifique las especificaciones y/o la fuente. El nuevo conocimiento lo convierte en un mejor desarrollador y reduce el riesgo de errores. –

2

La verificación del contenido solo es confiable para == cuando se comprueban los tipos primitivos. Para los tipos de objetos que siempre es mejor usar el método equals:

c.equals(d)