¿Cuál es la diferencia entre ==
y .equals()
en Scala, y cuándo usar cuál?
¿La implementación es la misma que en Java?
EDITAR: La pregunta relacionada se refiere a casos específicos de AnyVal
. El caso más general es Any
.
¿Cuál es la diferencia entre ==
y .equals()
en Scala, y cuándo usar cuál?
¿La implementación es la misma que en Java?
EDITAR: La pregunta relacionada se refiere a casos específicos de AnyVal
. El caso más general es Any
.
Respuestas:
Normalmente se utiliza ==
, se dirige a equals
, excepto que trata null
s correctamente. La igualdad de referencia (raramente utilizada) es eq
.
3 == BigInt(3)
y BigInt(3) == 3
son verdad. Pero, 3.equals(BigInt(3))
es falso, mientras que BigInt(3).equals(3)
es cierto. Por lo tanto, prefiera usar ==
. Evite usar equals()
en scala. Creo ==
que la conversión implícita funciona bien, pero equals()
no lo hace.
new java.lang.Integer(1) == new java.lang.Double(1.0)
es cierto mientras que new java.lang.Integer(1) equals new java.lang.Double(1.0)
es falso?
equals
Método de anulación para comparar el contenido de cada instancia. Este es el mismo equals
método utilizado en Java==
operador para comparar, sin preocuparse por las null
referencias.eq
método para verificar si ambos argumentos son EXACTAMENTE la misma referencia. Se recomienda no usar a menos que comprenda cómo funciona esto y, a menudo equals
, funcionará para lo que necesita. Y asegúrese de usar esto solo con AnyRef
argumentos, no soloAny
NOTA: en el caso de equals
, al igual que en Java, es posible que no devuelva el mismo resultado si cambia los argumentos, por ejemplo 1.equals(BigInt(1))
, devolverá false
donde regresará el inverso true
. Esto se debe a que cada implementación verifica solo tipos específicos. Los números primitivos no comprueban si el segundo argumento es de tipo Number
ni de BigInt
tipo, sino solo de otros tipos primitivos
El AnyRef.equals(Any)
método es el anulado por las subclases. Un método de la especificación Java que también se ha introducido en Scala. Si se usa en una instancia sin caja, está en caja para llamar a esto (aunque está oculto en Scala; más obvio en Java con int
-> Integer
). La implementación predeterminada simplemente compara referencias (como en Java)
El Any.==(Any)
método compara dos objetos y permite que cualquiera de los argumentos sea nulo (como si se llamara a un método estático con dos instancias). Compara si ambos son null
, luego llama al equals(Any)
método en la instancia en caja.
El AnyRef.eq(AnyRef)
método compara solo referencias, que es donde se encuentra la instancia en la memoria. No hay boxeo implícito para este método.
1 equals 2
regresará false
, ya que redirige aInteger.equals(...)
1 == 2
regresará false
, ya que redirige aInteger.equals(...)
1 eq 2
no se compilará, ya que requiere que ambos argumentos sean de tipo AnyRef
new ArrayList() equals new ArrayList()
regresará true
, ya que verifica el contenidonew ArrayList() == new ArrayList()
regresará true
, ya que redirige aequals(...)
new ArrayList() eq new ArrayList()
regresará false
, ya que ambos argumentos son instancias diferentesfoo equals foo
regresará true
, a menos que foo
sea null
, luego arrojará unNullPointerException
foo == foo
volverá true
, incluso si foo
esnull
foo eq foo
volverá true
, ya que ambos argumentos enlazan con la misma referenciaHay una diferencia interesante entre ==
y equals
para Float
y Double
tipos: tratan de manera NaN
diferente:
scala> Double.NaN == Double.NaN
res3: Boolean = false
scala> Double.NaN equals Double.NaN
res4: Boolean = true
Editar: como se señaló en un comentario, "esto también sucede en Java", depende de qué es exactamente esto :
public static void main(final String... args) {
final double unboxedNaN = Double.NaN;
final Double boxedNaN = Double.valueOf(Double.NaN);
System.out.println(unboxedNaN == unboxedNaN);
System.out.println(boxedNaN == boxedNaN);
System.out.println(boxedNaN.equals(boxedNaN));
}
Esto imprimirá
false
true
true
Entonces, los unboxedNan
rendimientos false
en comparación con la igualdad porque así es como lo definen los números de punto flotante IEEE y esto realmente debería suceder en todos los lenguajes de programación (aunque de alguna manera interfiere con la noción de identidad).
El NaN encuadrado rinde verdadero para la comparación usando ==
en Java ya que estamos comparando referencias de objeto.
No tengo una explicación para el equals
caso, en mi humilde opinión, realmente debería comportarse igual que ==
en los valores dobles sin caja, pero no lo hace.
Traducido a Scala, el asunto es un poco más complicado, ya que Scala ha unificado tipos primitivos y de objetos en Any
y se traduce en el doble primitivo y el Doble en caja según sea necesario. Por lo tanto, la escala ==
aparentemente se reduce a una comparación de NaN
valores primitivos , pero equals
usa el definido en valores dobles en caja (hay mucha magia de conversión implícita y hay cosas que se combinan en dobles RichDouble
).
Si realmente necesita saber si algo se NaN
usa realmente isNaN
: