본문 바로가기

Programming/Java

equals method 를 overriding 할 때 주의 점

우리는 클래스를 디자인 할 때, equals method 를 override 하게 되는 경우가 많다.


override 하게 될 경우, 중요한 사항들이 있으니 4가지 정도가 있다.


첫 번째부터 세 번째 까지는 수학에서 나오는 용어와 같다고 생각하면 된다.


1. Reflexivity - 어떤 객체는 자신과 동일해야 한다. 즉 A equals A 라고 할 수 있어야 한다. 아주 당연한 이야기 이겠지만, 그렇지 않을 수 있다.

2. Symmetry - 두 객체는 그것들이 동일하다고 판단되어야 한다. 예를 들어서, A equals B 라고 한다면, B equals A 라고 할 수 있어야 한다.

3. Transitivity - 첫 번째 객체가 두 번째 객체와 같고, 두 번째 객체가 세 번째 객체와 같다면, 첫 번째 객체는 세번째 객체와 같다고 말할 수 있어야 한다. 예를 들어보면, A equals B, B equals C => A equals C

4. Consistency - 만약 두 객체가 같다고 한다면, 그 두가지가 수정되는 않는 한 항상 같아야 한다.


추가적으로 우리가 흔히 실수하기 쉬운 코드는 equals method 안에서 필요없는 null 확인을 하여 프로그램의 성능을 떨어뜨리는 경우이다.

equals method 는 프로그램 내부적으로 정말 사용이 많이 되는 코드이다. 그렇기 때문에 효율적으로 작성해야 하는 것은 기본 중에 기본이다.


이해를 쉽게 하기 위해서 예를 들어보면, 아래의 코드는 언뜻 보면 당연히 수행해야 한다고 생각된다.


// 불필요한 코드를 사용하여 프로그램의 성능을 저하시키는 안 좋은 코드

@Override public boolean equals(Object o) {

    if (o == null)

        return false;

    ...

}


하지만, 아래의 코드에서 instanceof 연산자가 하는 일을 정확하게 아는 프로그래머라면 위의 null 확인 코드는 불필요하다는 것을 알고 있을 것이다. 왜냐하면 instanceof 연산자는 두 번째 인자가 무엇이든 간에 첫 번째 인자가 null 일 경우에는 false 를 돌려주기 때문이다. 아래의 instanceof 연산자를 사용하여 추가적으로 얻을 수 있는 이익은 ClassCastException 을 미연에 방지할 수 있다는 점이다.


// instanceof 연산자를 사용하여, null 체크, ClassCastException 을 방지하는 산뜻한 코드

@Override public boolean equals(Object o) {

    if (! (o instanceof MyType))

        return false;

    ...

}


- From Effective Java 2nd Edition by Joshua Bloch