자바에서 equals메소드의 오버라이딩 규칙
조회수 3360회
구글링으로 자바를 공부하고 있는데요 웬만하면 equals를 오버라이딩하지말고 상속받은 그대로 사용하는 편이 좋다라는 글을 보았습니다. 그래도 equals를 오버라이딩하고 싶으면 어떤 규칙을 만족할때만 하라고 했는데요. 예전에 글을 보고 이번에 실습하면서 짜보려고 했지만 그 글이 기억이 잘 나지 않습니다. 해당 페이지를 다시 찾아보고 싶었지만 어떻게 검색했는지도 잊어버려서 찾을 수가 없습니다. 보편적인 규칙이라고 하니 대부분의 자바개발자는 숙지하고 계실것 같은데 혹시 아시는분 계신가요?
1 답변
-
이펙티브 자바라는 책에서 비슷한 내용을 본적 있는데요. 밑의 사항중 하나라도 만족하는 경우는 equals를 상속받은 그대로 사용하시는게 좋습니다. 하나도 만족하지 않는다면 오버라이딩 해도 좋다는 말도 되죠.
이펙티브 자바의 챕터3의 항목8을 보면 equals메소드를 오버라이딩 할때는 보편적 계약을 따르자 라는 내용이 있습니다. 내용은 이렇습니다.
- 클래스의 각 인스턴스가 본래부터 유일한 경우. 인스턴스가 갖는 값보다는 활동하는 개체임을 나타내는 것이 더 중요한 Thread와 같은 클래스가 여기에 해당된다. 그런 클래스들은 인스턴스가 갖는 값의 논리적인 비교는 의미가 없으며, 객체 참조가 같으면 동일한 것임을 알 수 있기 때문에 Object의 equals를 그냥 사용하면 된다.
- 두 인스턴스가 논리적으로 같은지 검사하지 않아도 되는 클래스의 경우. 예를 들어, java.util.Random클래스에서는 두 개의 Random 인스턴스가 같은 난수열을 만드는지 확인하기 위해 equals 메소드를 오버라이딩 할 수 있었을 것이다. 그러나 그 클래스의 설계자는 클라이언트가 그런 기능을 원한다고 생각하지 않았다. 이런 경우 Object로부터 상속받은 equals를 그냥 쓰면 된다.
- 수퍼 클래스에서 equals 메소드를 이미 오버라이딩 했고, 그 메소드를 그대로 사용해도 좋은 경우. 예를 들어 Set 인터페이스를 구현하는 대부분의 클래스들은 AbstractSet에 구현된 equals를 상속받아 사용하며, List의 경우는 AbstractList로 부터, Map의 경우는 AbstractMap에서 상속받아 사용한다.
- private이나 패키지 전용 클래스라서 이 클래스의 equals메소드가 절대 호출되지 않아야 할 경우. 우연히 호출될 수 있는 그런 상황에서는 다음과 같이 equals메소드를 반드시 오버라이딩해서 호출되지 않도록 해야한다.
@Override public boolean equals(Object o){ throw new AssertionError();//메소드가 절대 호출되지 않는다. }
Object.equals를 언제 오버라이딩하면 좋을까?
객체 참조만으로 인스턴스의 동일 여부를 판단하는 것이 아니라, 인스턴스가 갖는 값을 비교하여 논리적으로 같은지 판단할 필요가 있는 클래스로써, 자신의 수퍼클래스에서 equals메소드를 오버라이딩 하지 않았을 때 하면 좋습니다.
예를들어 Integer나 Date같은 값을 나타내는 클래스의 경우 equals메소드를 오버라이딩할 필요가 있습니다.
댓글 입력