A getter that hands out the internals
A medium Java puzzle in the shared and static mutable state family. One line below contains a real bug. Try to spot it first, then read why it fails and how to fix it.
Highlighted: line 8. Play this one as a puzzle without the answer.
What is wrong
Date is mutable. A caller can call getExpires().setTime(...) and extend the subscription without going through the class, and the constructor stored the caller's own object too. The final field protects the reference, not the value.
The fix
How to avoid it next time
Return immutable types such as Instant, or defensive copies, and copy mutable arguments in the constructor.
Want the background? Read Immutability and final classes in the Java concepts library.
About shared and static mutable state
Static fields and singleton beans are shared by every request and thread. Mutable state kept there leaks data between users, makes tests order-dependent and creates race conditions that appear only under load.
In code review: Look for non-final static fields and instance fields in singleton beans that are written during a request. Prefer local variables, immutable objects and explicit synchronization.
More puzzles in this family
Frequently asked questions
What is the bug in "A getter that hands out the internals"?
Date is mutable. A caller can call getExpires().setTime(...) and extend the subscription without going through the class, and the constructor stored the caller's own object too. The final field protects the reference, not the value. The faulty line is line 8: public Date getExpires() { return expires; }
How do I fix it?
Replace it with: public Instant getExpires() { return expires.toInstant(); } // or return new Date(expires.getTime()). Return immutable types such as Instant, or defensive copies, and copy mutable arguments in the constructor.
How do I catch shared and static mutable state in code review?
Look for non-final static fields and instance fields in singleton beans that are written during a request. Prefer local variables, immutable objects and explicit synchronization.
Is there a new puzzle every day?
Yes. The daily Spot the Bug puzzle picks one of these snippets for each UTC day, with the difficulty set by the weekday. Your streak is stored only in your browser.