5. 자주 하는 실수 (Tip)
❌ 실수 1: equals(Member o) 로 오버로드한다
public boolean equals(Member o) { return id == o.id; } // Object.equals 를 덮지 않는다. 컬렉션은 여전히 == 로 비교@Override 를 붙이면 "메서드가 상위 타입의 메서드를 오버라이드하지 않습니다" 로 컴파일러가 잡아 줍니다.
❌ 실수 2: equals 만 정의하고 hashCode 를 빠뜨린다
예제 2 의 Point 입니다. IDE 의 자동 생성(Generate equals and hashCode)을 쓰면 항상 같이 만들어 줍니다. 둘 중 하나만 있으면 코드 리뷰에서 반드시 잡아야 합니다.
❌ 실수 3: equals 에 없는 필드를 hashCode 에 넣는다
public boolean equals(Object o) { ... return id == other.id; }
public int hashCode() { return Objects.hash(id, name); } // name 이 다르면 해시가 다르다 → 같은 회원이 다른 버킷❌ 실수 4: compareTo 를 뺄셈으로 만든다
public int compareTo(Order o) { return (int) (no - o.no); } // long → int 절단, 큰 값에서 부호 뒤집힘
public int compareTo(Order o) { return Long.compare(no, o.no); } // ✅❌ 실수 5: BigDecimal 을 equals 로 비교한다
new BigDecimal("1.0").equals(new BigDecimal("1.00")) 은 false 입니다. 금액 비교는 compareTo(...) == 0, 집합·키로 쓰려면 setScale 로 통일하거나 stripTrailingZeros().
❌ 실수 6: toString 에 민감 정보를 넣는다
Member{id=7, password=1234} 가 로그에 남습니다. 비밀번호·주민번호·카드번호는 제외하고, record 라면 toString 을 다시 정의합니다.
❌ 실수 7: Comparator 에서 null 을 처리하지 않는다
Comparator.comparing(Order::customer) 에 customer 가 null 인 원소가 있으면 NullPointerException. nullsFirst/nullsLast 로 감싸거나 데이터 단계에서 null 을 막습니다.