Avertissement égal à / hashCode sur l'annotation @Data lombok avec héritage

103

J'ai une entité qui hérite des autres. D'un autre côté, j'utilise le projet lombok pour réduire le code standard, alors j'ai mis une @Dataannotation. L'annotation @Dataavec héritage produit l'avertissement suivant:

Génération de l'implémentation equals / hashCode mais sans appel à la superclasse, même si cette classe n'étend pas java.lang.Object. Si c'est intentionnel, ajoutez @EqualsAndHashCode(callSuper=false)à votre type.

Est-il conseillé d'ajouter une annotation @EqualsAndHashCode (callSuper = true)ou @EqualsAndHashCode (callSuper = false)? S'il n'est pas ajouté, lequel est-ce callSuper=falseou callSuper=true?

Pau
la source

Réponses:

125

La valeur par défaut est false. C'est celui que vous obtenez si vous ne le spécifiez pas et ignorez l'avertissement.

Oui, il est recommandé d'ajouter une @EqualsAndHashCodeannotation sur les @Dataclasses annotées qui étendent autre chose que Object. Je ne peux pas vous dire si vous avez besoin trueou false, cela dépend de votre hiérarchie de classe, et devra être examiné au cas par cas.

Cependant, pour un projet ou un package, vous pouvez configurer in lombok.configpour appeler les super méthodes s'il ne s'agit pas d'une sous-classe directe d'Object.

lombok.equalsAndHashCode.callSuper = call

Consultez la documentation du système de configuration pour savoir comment cela fonctionne et la @EqualsEndHashCodedocumentation des clés de configuration prises en charge.

Divulgation: Je suis un développeur lombok.

Roel Spilker
la source
A travaillé pour moi. Mais gardez simplement à l'esprit que pour que le plugin delombok récupère ce fichier de configuration, il doit être placé dans le répertoire racine des sources java, pas dans le répertoire resources, c'est-à-dire dans src / main / java et pas dans src / main / resources
user577736
1
@Roel Je me demande pourquoi la valeur par défaut est false. J'aurais attendu le contraire. De plus, y a-t-il un moyen équivalent d'obtenir toString () pour appeler super par défaut? Je vois que je peux faire "@ToString (callSuper = true)", mais je ne vois aucun paramètre de configuration de ce type. Merci.
David Siegal
Est-ce important si j'ajoute @EqualsAndHashCode (callSuper = true) avant ou après @Data?
Anna Klein
@AnnaKlein l'ordre n'a pas d'importance
dan carter
47

@EqualsAndHashCode(callSuper=true) devrait résoudre l'avertissement.

noscreenname
la source
1
Cela devrait être la réponse acceptée car je ne pense pas que la suggestion de Roel devrait être faite "lombok.equalsAndHashCode.callSuper = call" à la place, une décision devrait être prise pour chaque classe.
Anna Klein
4
@AnnaKlein Je ne pense pas. En fait cette réponse devrait être un commentaire, il n'y a pas de nouvelles informations ici, vous pouvez trouver cela dans ma question. Je savais que @EqualsAndHashCoderésout l'avertissement.
Pau
En fait, selon la réponse acceptée (et ma réponse ci-dessous), vous devez choisir entre «callSuper = true» ou «callSuper = false» dans l'annotation.
Adam Wise
27

La principale question originale est:

Est-il conseillé d'ajouter l'annotation @EqualsAndHashCode (callSuper = true) ou @EqualsAndHashCode (callSuper = false)?

La réponse acceptée est fondamentalement juste:

...ça dépend...

Pour développer cela, la documentation sur @EqualsAndHashCode propose des conseils solides sur le choix. Surtout cela, à mon humble avis:

En définissant callSuper sur true, vous pouvez inclure les méthodes equals et hashCode de votre superclasse dans les méthodes générées. Pour hashCode, le résultat de super.hashCode () est inclus dans l'algorithme de hachage, et Forequals, la méthode générée retournera false si la super implémentation pense qu'il n'est pas égal à l'objet passé. Sachez que toutes les implémentations égales ne gèrent pas correctement cette situation. Cependant, les implémentations d'égalité générées par lombok gèrent cette situation correctement, vous pouvez donc appeler votre superclasse égale en toute sécurité si elle possède également une méthode d'égalité générée par lombok.

Pour distiller un peu ceci: Choisissez 'callSuper = true' si vous héritez d'une superclasse qui n'a pas d'informations d'état, ou utilise elle-même l'annotation @Data, ou a des implémentations de equals / hash qui "gèrent la situation correctement" - ce que j'interprète comme signifiant renvoyer un hachage approprié des valeurs d'état.

Adam Wise
la source
Je pense que c'est la réponse qui explique bien comment choisir entre callSuper = false et callSuper = true.
prageeth le
10

Si vous souhaitez également comparer les membres de la superclasse, utilisez @EqualsAndHashCode(callSuper=true). Si, cependant, vous souhaitez comparer uniquement les champs de la classe actuelle, vous pouvez utiliser @EqualsAndHashCode(callSuper=false)la valeur par défaut option .

Si vous utilisez la fonction Delombok, vous pouvez voir que la différence est que lorsqu'elle est définie sur truecette ligne, elle est ajoutée à la méthode d' égalité générée if (!super.equals(o)) return false;. Si vous avez des membres dans la superclasse qui doivent être pris en compte lors de la comparaison de deux objets, alors il doit être défini sur true pour pouvoir comparer correctement.

EvR2f
la source