스칼라에서 ==와 .equals의 차이점은 무엇입니까?


144

스칼라 ==와 의 차이점은 무엇 .equals()이며 언제 사용해야합니까?

구현이 Java와 동일합니까?

편집 : 관련 질문은의 특정 사례에 대해 이야기 AnyVal합니다. 더 일반적인 경우는 Any입니다.



@Ben 다른 질문은 요청한 날짜를 고려하여 중복으로 표시해야한다고 생각합니다. 또한 두 가지 질문이 다르다고 생각합니다.
Jus12

답변:


201

일반적 으로을 (를) 올바르게 처리하는 것을 제외하고로 ==라우팅합니다 . 참조 평등 (드물게 사용됨)은 입니다.equalsnulleq


12
Java 라이브러리를 사용할 때도 적용됩니까?
Jus12

20
그렇습니다. 예를 들어, new java.util.ArrayList [Int] () == new java.util.ArrayList [Int] ()는 ArrayList와 동일하므로 컨텐츠가 동일합니다.
Didier Dupont

5
Int와 Long 및 == vs .equals ()와 관련하여 이상한 동작이 있습니다. Int 및 Long과 같은 숫자는 ==에 대해서는 true를 반환하지만 같으면 false를 반환합니다. 따라서 ==가 항상 같음으로 라우팅되는 것은 아닙니다.
해롤드 L

24
더 흥미롭게도, 모두 3 == BigInt(3)BigInt(3) == 3사실이다. 그러나 사실 3.equals(BigInt(3))은 거짓 BigInt(3).equals(3)입니다. 따라서을 사용하는 것이 ==좋습니다. equals()스칼라에서는 사용하지 마십시오 . 나는 ==암묵적인 변환을 잘 한다고 생각 하지만 equals()그렇지 않습니다.
Naetmul

new java.lang.Integer(1) == new java.lang.Double(1.0)진정한 동안은 new java.lang.Integer(1) equals new java.lang.Double(1.0)거짓?
Eastsun

34

==최종 방법이며,를 호출합니다 .equals.

이것은 ==메소드가 아닌 연산자 인 Java와 근본적으로 다르며 객체의 참조 평등을 엄격하게 비교합니다.


29

TL; DR

  • equals각 인스턴스의 컨텐츠를 비교하는 메소드를 대체하십시오 . 이것은 equalsJava에서 사용 된 것과 동일한 방법입니다
  • 참조 ==를 걱정하지 않고 연산자를 사용 하여 비교null
  • 사용하여 eq두 인수가 있는지 확인하는 방법을 정확하게 동일한 참조. 이것이 어떻게 작동하는지 이해하지 못하고 종종 equals대신 필요한 것에서 작동하지 않는 한 사용하지 않는 것이 좋습니다. 그리고 이것을 AnyRef인수가 아닌 인수 와 함께 사용해야합니다.Any

참고 : 경우에 equals당신은 예를 들어이 인수 전환하면 바로 자바로,이 같은 결과를 반환하지 않을 수 있습니다 1.equals(BigInt(1))반환 false역 반환 곳을 true. 각 구현이 특정 유형 만 검사하기 때문입니다. 기본 숫자는 두 번째 인수가 유형이 아닌 다른 기본 유형 인지 확인하지 Number않습니다.BigInt

세부

AnyRef.equals(Any)메소드는 서브 클래스로 대체 된 메소드입니다. 스칼라에 온 Java 스펙의 메소드. 박스가없는 인스턴스에서 사용되는 경우이를 호출하는 박스가 있습니다 (스칼라에는 숨겨져 있지만 Java에서는 int->가 더 분명합니다 Integer). 기본 구현은 단지 참조를 비교합니다 (Java와 동일).

Any.==(Any)메소드는 두 객체를 비교하고 두 인스턴스를 사용하여 정적 메소드를 호출하는 것처럼 두 인수를 모두 널로 허용합니다. 둘 다 인 경우를 비교 null한 다음 equals(Any)박스형 인스턴스 에서 메소드를 호출합니다 .

AnyRef.eq(AnyRef)방법은 참조, 즉 인스턴스가 메모리에있는 위치 비교 합니다 . 이 방법에 대한 암시 적 권투는 없습니다.

  • 1 equals 2false로 리디렉션 될 때를 반환 합니다.Integer.equals(...)
  • 1 == 2false로 리디렉션 될 때를 반환 합니다.Integer.equals(...)
  • 1 eq 2 두 인수 모두 유형이어야하므로 컴파일되지 않습니다. AnyRef
  • new ArrayList() equals new ArrayList()true내용을 확인하면서를 반환 합니다.
  • new ArrayList() == new ArrayList()true로 리디렉션 될 때를 반환 합니다.equals(...)
  • new ArrayList() eq new ArrayList()false두 인수가 서로 다른 인스턴스이므로를 반환 합니다.
  • foo equals foo반환 true하지 않는 foo것입니다 null, 다음을 던질 것이다NullPointerException
  • foo == foo반환합니다 true경우에도 foo입니다null
  • foo eq footrue두 인수가 동일한 참조에 연결되므로 가 반환됩니다.

6

사이에 흥미로운 차이가 ==equals에 대한 FloatDouble유형 : 그들은 치료 NaN다르게 :

scala> Double.NaN == Double.NaN
res3: Boolean = false

scala> Double.NaN equals Double.NaN
res4: Boolean = true

편집 : 의견에서 지적했듯이 "이것은 Java에서도 발생합니다" 는 정확히 이것이 무엇인지에 달려 있습니다 .

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));
}

이것은 인쇄됩니다

false
true
true

따라서 IEEE 부동 소수점 숫자가 그것을 정의하는 방식이기 때문에 평등과 비교할 때 의 unboxedNan수율 false은 모든 프로그래밍 언어에서 실제로 발생해야합니다 (어쨌든 정체성의 개념을 엉망으로 만듭니다).

박스형 NaN은 ==객체 참조를 비교할 때 Java를 사용한 비교에 적용됩니다.

이 경우에 대한 설명이 없습니다 equals.IMHO는 실제로 상자 ==가없는 이중 값 과 동일하게 작동해야 하지만 그렇지 않습니다.

스칼라로 번역하면 스칼라는 프리미티브와 객체 유형을 통합 Any하여 필요에 따라 프리미티브 더블과 박스형 더블로 변환 하기 때문에 조금 더 복잡 합니다. 따라서 스칼라 ==는 기본 NaN값 의 비교로 요약 되지만 equals박스형 Double 값에 정의 된 값을 사용합니다 (암시 적 변환 마술이 많이 진행되고 있으며으로 double에 포주가있는 물건이 있습니다 RichDouble).

실제로 무언가가 NaN사용되고 있는지 알아 내야하는 경우 isNaN:


그리고 이것은 Java에서도 발생합니다!
Iwan Satria

4

Scala ==에서 먼저 Null 값을 확인한 다음 첫 번째 객체에서 equals 메서드 를 호출 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.