자바의 최상위 클래스인 Object 클래스에는 equals(), hashCode(), toString(), clone(), notify() 등 여러 native 메서드가 존재한다. 그중에서 equals()에 대해서 알아보자.
객체를 비교할 때 == 연산자와 equals() 메서드를 사용할 수 있다. 둘의 차이점은 뭘까?
== 연산자
단순하게 말하자면 == 연산자는 int, boolean과 같은 primitive type에 대해서는 값을 비교한다. reference type에 대해서는 주소값을 비교한다.사실 엄밀히 따지면 primitive type 역시 Constant Pool에 있는 특정 상수를 참조하는 것이기 때문에 결국 주소값을 비교하는 것으로 볼 수 있다.같은 상수를 참조하면 주소값이 같으니 결국 같은 값이면 동일하다고 판단할 수 있기 때문이다.
간단한 예제를 하나 보자.
Line 7에서 선언한 Person 객체가 0x100 주소에 생성되었다고 가정하자. 그러면 참조형 변수 person1의 값은 해당 주소값인 0x100이 된다. Line 8의 person2는 0x200을 참조한다고 가정하자. 그림으로 그리면 다음과 같다.
이렇게 보면 결국 int 타입인 a, b 변수가 값을 비교하듯이 참조형 변수인 person1, person2, person3가 주소값을 비교한다는 의미가 결국 해당 변수의 값을 비교하는 것이다.
equals()
equals() 메서드는 최상위 클래스인 Object에 포함되어 있기 때문에 모든 하위 클래스에서 재정의하여 사용할 수 있다. 따라서 equals()는 사용자가 어떻게 재정의하느냐에 따라서 원하는 기준으로 비교 가능하다.
보통 String 타입을 비교할 때 '내용'이 같은지 비교한다고 설명한다. 그 이유는 String 클래스에서 eqauls()를 문자열 내용이 같으면 true를 리턴하도록 재정의했기 때문이다.
String 클래스의 equals()는 다음과 같이 재정의되어 있다.
문자열을 char 단위로 한 글자씩 모두 비교하여 동일하면 true를 리턴한다. 따라서 서로 다른 객체라도 같은 문자열을 가지고 있으면 동일하다고 판단하는 것이다.
이번엔 좀 더 심화된 예제를 보자.
String은 문자열을 바로 참조할 경우 같은 주소값을 가질 수도 있다.
Line 3~4는 동일한 문자열을 String Constant Pool에서 곧바로 참조한 것이다.
Line 8~9는 객체 2개를 만들고 각 객체의 멤버 변수인 name에 문자열을 할당한다.
이 부분을 그림으로 표현하면 다음과 같다.
Line 5의 결과가 true가 되는 것은 str1과 str2의 주소값이 동일하기 때문이다. str1과 str2는 동일한 문자열 상수를 참조하고 있어서 주소값이 동일한 것이다.
Line 6의 결과가 true가 되는 것은 String 객체의 equals() 메서드가 각 문자열이 글자를 하나씩 비교해서 동일하다고 판단했기 때문이다. 두 객체 모두 hello라는 동일한 문자열을 가졌기 때문이다.
Line 10은 str3과 str4는 서로 다른 주소값을 가지고 있기 때문에 false이다.
Line 11은 abc라는 동일한 문자열을 가진 String 객체이기 때문에 재정의된 equals()의 결과로 true가 된다.
Line 13~15의 Person 객체와 관련된 부분의 그림은 다음과 같다.
Line 31에서 Person 클래스의 equals() 메서드를 재정의했다. 내용을 보면 멤버 변수인 name의 문자열이 동일한지 비교하고 있다.
Line 16은 person1과 person2의 주소값 비교이기 때문에 false이다.
Line 17은 Person 클래스에서 재정의된 equals()를 사용한다. 따라서 두 객체의 name의 문자열이 kim으로 동일하기 때문에 true이다. person2는 name에 값을 할당할 때 new String("kim")으로 했기 때문에 새로운 String 객체를 생성한 것이다. 따라서 만약 equals()를 재정의할 때 return (this.name == anotherObj.name); 과 같이 했다면 fasle가 될 것이다. 왜냐면 name이 가리키는 주소값은 다르기 때문이다.
Line 18~19 : person2와 person3은 주소값이나 name에 할당된 문자열이나 모두 같기 때문에 true가 된다.
사실 hashCode()에 대해서 포스팅하려고 했는데 == 연산자와 equals()와 비교하기 위해서 내용을 정리하다 보니 시간이 훌쩍 지나갔다. hashCode()는 다음에 이어서 살펴봐야겠다.