From 7cbb5e9d4ad2a8e308711d0a9c59fc4f2c5292a8 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 20 Sep 2023 04:24:19 +0200 Subject: [PATCH] [fixes #3182] [docs] Add a note about wonky equality definitions in the core libraries (BigDecimal in particular) to the docs of EqualsAndHashCode --- website/templates/features/EqualsAndHashCode.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/templates/features/EqualsAndHashCode.html b/website/templates/features/EqualsAndHashCode.html index 474b4ee2a7..e7431bfd4c 100644 --- a/website/templates/features/EqualsAndHashCode.html +++ b/website/templates/features/EqualsAndHashCode.html @@ -8,6 +8,10 @@ If applying @EqualsAndHashCode to a class that extends another, this feature gets a bit trickier. Normally, auto-generating an equals and hashCode 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 callSuper to true, you can include the equals and hashCode methods of your superclass in the generated methods. For hashCode, the result of super.hashCode() is included in the hash algorithm, and forequals, 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 equals implementations handle this situation properly. However, lombok-generated equals implementations do handle this situation properly, so you can safely call your superclass equals if it, too, has a lombok-generated equals method. If you have an explicit superclass you are forced to supply some value for callSuper to acknowledge that you've considered it; failure to do so results in a warning.

Setting callSuper to true when you don't extend anything (you extend java.lang.Object) is a compile-time error, because it would turn the generated equals() and hashCode() implementations into having the same behaviour as simply inheriting these methods from java.lang.Object: only the same object will be equal to each other and will have the same hashCode. Not setting callSuper to true 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 callSuper chaining facility. You can also use the lombok.equalsAndHashCode.callSuper config key. +

+ Note that lombok just defers to the .equals() implementation for all objects except primitives and arrays. Some well known types have possibly surprising equals implementations. For example, java.math.BigDecimal considers scale, i.e. 1E2 is not equal to 100 according to BigDecimal's own equals implementation. +

+ CAUTION: It is easy to override the equals behaviour for any field by writing a method that returns a mapped value and annotating it with @EqualsAndHashCode.Include(replaces = "fieldName"). For example, to address the BigDecimal equality issue, you could write @EqualsAndHashCode.Include BigDecimal fieldName() { return fieldName.stripTrailingZeros(); }.

NEW in Lombok 0.10: Unless your class is final and extends java.lang.Object, lombok generates a canEqual 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: How to Write an Equality Method in Java. 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 canEqual if you change equals and hashCode.