Subclass: object is not equal to an instance of a trivial subclass with equal fields: ... Consider making the class final.
This error occurs when a class is non-final, and an instance of this class is not equal to an instance of a (dynamically generated) subclass of this class, even though their fields are all equal. It is easy to break the equals contract when inheritance is involved, even accidentally, and EqualsVerifier will always err on the side of caution.
There are several ways to fix this problem:
Make the class final
Make the class final. This way, all inheritance headaches will be avoided. However, this is not always possible.
In frameworks like Java EE and Hibernate, it’s often not allowed to make certain classes final, even if you don’t intend to subclass them. In these cases, it’s probably a safe bet that the framework will create dynamic proxy subclasses for you class. This error will most likely only pop up if you use
getClass() in your equals method, like so:
The solution, then, is to use an
instanceof test instead:
This way, a dynamic proxy subclass generated by the framework can still be equal to an object that you instantiate directly.
Unfortunately, with Hibernate it’s not possible to make the
hashCode methods final as well. This means it’s still possible to accidentally (or purposely) break the contract by making a subclass and overriding
If you do intend your class to be overridden, but subclasses won’t add state that needs to be included in the
hashCode contract, the above advice applies as well. Again, make you
hashCode methods final, to signal that no such state is to be added in subclasses.
If you intend your class to be overridden, and you also want subclasses to add state that needs to be included in the contract, things get complicated. In Item 8 of Effective Java, Josh Bloch argues that it is impossible to achieve this without breaking the contract. Nevertheless, it turns out to be possible, by introducing a new method called
canEqual. This article by Martin Odersky, Bill Venners and Lex Spoon explains how to achieve this. If you decide to go down this path, you will need to supply EqualsVerifier with an example of a subclass with added state, like this:
Obligatory RTFM comment
You can read more about handling inheritance in the manual.