equals만 구현하고 hashCode를 빠뜨림public final class Point {
int x, y;
@Override public boolean equals(Object o) {
return o instanceof Point p && p.x == x && p.y == y;
}
// hashCode 없음
}
Set<Point> s = new HashSet<>();
s.add(new Point(1, 2));
System.out.println(s.contains(new Point(1, 2))); // false!HashSet은 먼저 hashCode로 버킷을 찾고 그 안에서 equals를 봅니다. hashCode가 다르면 equals는 호출조차 되지 않습니다.
✅ 항상 쌍으로 구현합니다.
@Override public int hashCode() { return Objects.hash(x, y); }public List<String> getItems() { return items; }
order.getItems().clear(); // 바깥에서 주문 내용이 통째로 사라짐주소를 돌려줬으므로 호출자가 내 필드를 직접 조작하는 것과 같습니다.
✅ 불변 뷰 또는 복사본을 돌려줍니다.
public List<String> getItems() { return Collections.unmodifiableList(items); }null 반환public List<String> findTags(String post) {
if (noTags) return null;
...
}
for (String t : findTags(p)) { ... } // NullPointerException호출자 모두가 null 검사를 해야 하고, 하나라도 빠지면 NPE입니다.
✅ 빈 컬렉션을 돌려줍니다: return List.of();
compareTo에서 뺄셈으로 비교@Override public int compareTo(Money o) {
return (int) (amount - o.amount); // long → int 잘림, 오버플로우
}amount = Long.MAX_VALUE, o.amount = -1이면 결과가 음수가 되어 순서가 뒤집힙니다. int끼리도 Integer.MIN_VALUE - 1에서 터집니다.
✅ Long.compare(amount, o.amount) 또는 Comparator.comparingLong(Money::amount)를 씁니다.
Money m = Money.of(1000);
m.withAmount(5000);
m.plus(Money.of(100));
System.out.println(m); // 1,000원 — 아무것도 안 바뀜불변 객체의 메서드는 자신을 바꾸지 않고 새 객체를 돌려줍니다.
✅ 반환값을 받습니다: m = m.withAmount(5000).plus(Money.of(100));
equals 매개변수 타입을 바꿔서 오버로딩이 됨public boolean equals(Money o) { // Object가 아니라 Money
return amount == o.amount;
}
List<Money> list = List.of(Money.of(1));
System.out.println(list.contains(Money.of(1))); // false — Object.equals가 호출됨컬렉션은 equals(Object)를 부릅니다. equals(Money)는 별개의 오버로딩이라 무시됩니다.
✅ @Override public boolean equals(Object o)로 쓰고 @Override를 붙여 컴파일러가 잡게 합니다.
public abstract class Report {
public String generate(List<String> rows) { ... } // final이 아님
}
class BadReport extends Report {
@Override public String generate(List<String> rows) { return "아무거나"; } // 골격 무시
}템플릿의 목적은 "순서를 고정"하는 것인데 자식이 통째로 바꿀 수 있으면 의미가 없습니다.
✅ 템플릿 메서드는 public final로 선언합니다.