Skip to content

Commit

Permalink
[fixes #3182] [docs] Add a note about wonky equality definitions in t…
Browse files Browse the repository at this point in the history
…he core libraries (BigDecimal in particular) to the docs of EqualsAndHashCode
  • Loading branch information
rzwitserloot committed Sep 20, 2023
1 parent 9bcaaaf commit 7cbb5e9
Showing 1 changed file with 4 additions and 0 deletions.
4 changes: 4 additions & 0 deletions website/templates/features/EqualsAndHashCode.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
If applying <code>@EqualsAndHashCode</code> to a class that extends another, this feature gets a bit trickier. Normally, auto-generating an <code>equals</code> and <code>hashCode</code> method for such classes is a bad idea, as the superclass also defines fields, which also need equals/hashCode code but this code will not be generated. By setting <code>callSuper</code> to <em>true</em>, you can include the <code>equals</code> and <code>hashCode</code> methods of your superclass in the generated methods. For <code>hashCode</code>, the result of <code>super.hashCode()</code> is included in the hash algorithm, and for<code>equals</code>, the generated method will return false if the super implementation thinks it is not equal to the passed in object. Be aware that not all <code>equals</code> implementations handle this situation properly. However, lombok-generated <code>equals</code> implementations <strong>do</strong> handle this situation properly, so you can safely call your superclass equals if it, too, has a lombok-generated <code>equals</code> method. If you have an explicit superclass you are forced to supply some value for <code>callSuper</code> to acknowledge that you've considered it; failure to do so results in a warning.
</p><p>
Setting <code>callSuper</code> to <em>true</em> when you don't extend anything (you extend <code>java.lang.Object</code>) is a compile-time error, because it would turn the generated <code>equals()</code> and <code>hashCode()</code> implementations into having the same behaviour as simply inheriting these methods from <code>java.lang.Object</code>: only the same object will be equal to each other and will have the same hashCode. Not setting <code>callSuper</code> to <em>true</em> when you extend another class generates a warning, because unless the superclass has no (equality-important) fields, lombok cannot generate an implementation for you that takes into account the fields declared by your superclasses. You'll need to write your own implementations, or rely on the <code>callSuper</code> chaining facility. You can also use the <code>lombok.equalsAndHashCode.callSuper</code> config key.
</p><p>
Note that lombok just defers to the <code>.equals()</code> implementation for all objects <em>except</em> primitives and arrays. Some well known types have possibly surprising equals implementations. For example, <code>java.math.BigDecimal</code> considers scale, i.e. <code>1E2</code> is not equal to <code>100</code> according to <code>BigDecimal</code>'s own <code>equals</code> implementation.
</p><p>
<em>CAUTION: </em> It is easy to override the equals behaviour for any field by writing a method that returns a mapped value and annotating it with <code>@EqualsAndHashCode.Include(replaces = "fieldName")</code>. For example, to address the <code>BigDecimal</code> equality issue, you could write <code>@EqualsAndHashCode.Include BigDecimal fieldName() { return fieldName.stripTrailingZeros(); }</code>.
</p><p>
<em>NEW in Lombok 0.10: </em>Unless your class is <code>final</code> and extends <code>java.lang.Object</code>, lombok generates a <code>canEqual</code> method which means JPA proxies can still be equal to their base class, but subclasses that add new state don't break the equals contract. The complicated reasons for why such a method is necessary are explained in this paper: <a href="https://www.artima.com/lejava/articles/equality.html">How to Write an Equality Method in Java</a>. If all classes in a hierarchy are a mix of scala case classes and classes with lombok-generated equals methods, all equality will 'just work'. If you need to write your own equals methods, you should always override <code>canEqual</code> if you change <code>equals</code> and <code>hashCode</code>.
</p><p>
Expand Down

0 comments on commit 7cbb5e9

Please sign in to comment.