Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/bugpattern/ThrowableEqualsHashCode.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,38 @@ Throwables should not override `equals()` or `hashCode()`.
Exceptions for normal business logic or control flow, which is a known
anti-pattern. Exceptions are for exceptional circumstances; they are heavy
(because of the stack trace) and slow to generate.

### **Recommended Alternative: A separate value object**

If you find yourself needing to compare exceptions, **extract the state into a
separate value object.**

Instead of this:

```java
public class UserNotFoundException extends RuntimeException {
private final String userId;
private final String groupId;

// Override equals and hashCode based on userId and groupId...
}
```

Do this: Create a custom Exception that *contains* a value object (like a Record
or a POJO), and compare the value objects instead.

```java
public class UserNotFoundException extends RuntimeException {
private final ErrorDetails details;

public UserNotFoundException(ErrorDetails details) {
super("%s is not a member of %s:".formatted(details.userId(), details.groupId()));
this.details = details;
}

public ErrorDetails getDetails() { return details; }
}

// Compare the details, not the exceptions!
if (e1.getDetails().equals(e2.getDetails())) { ... }
```
Loading