¿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 nulls correctamente. La igualdad de referencia (raramente utilizada) es eq.
3 == BigInt(3)y BigInt(3) == 3son 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?
equalsMétodo de anulación para comparar el contenido de cada instancia. Este es el mismo equalsmétodo utilizado en Java==operador para comparar, sin preocuparse por las nullreferencias.eqmé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 AnyRefargumentos, no soloAnyNOTA: 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á falsedonde 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 Numberni de BigInttipo, 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 2regresará false, ya que redirige aInteger.equals(...)1 == 2regresará false, ya que redirige aInteger.equals(...)1 eq 2 no se compilará, ya que requiere que ambos argumentos sean de tipo AnyRefnew 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 fooregresará true, a menos que foosea null, luego arrojará unNullPointerExceptionfoo == foovolverá true, incluso si fooesnullfoo eq foovolverá true, ya que ambos argumentos enlazan con la misma referenciaHay una diferencia interesante entre ==y equalspara Floaty Doubletipos: tratan de manera NaNdiferente:
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 unboxedNanrendimientos falseen 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 equalscaso, 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 Anyy 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 NaNvalores primitivos , pero equalsusa 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 NaNusa realmente isNaN: