Les constructeurs commons / lang sont excellents et je les utilise depuis des années sans surcharge de performance notable (avec et sans mise en veille prolongée). Mais comme l'écrit Alain, la manière Goyave est encore plus agréable:
Voici un exemple de Bean:
public class Bean{
private String name;
private int length;
private List<Bean> children;
}
Voici equals () et hashCode () implémentés avec Commons / Lang:
@Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
et ici avec Java 7 ou supérieur (inspiré de Guava):
@Override
public int hashCode(){
return Objects.hash(name, length, children);
}
@Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return Objects.equals(name, other.name)
&& length == other.length // special handling for primitives
&& Objects.equals(children, other.children);
} else{
return false;
}
}
Remarque: ce code faisait à l'origine référence à Guava, mais comme les commentaires l'ont souligné, cette fonctionnalité a depuis été introduite dans le JDK, donc Guava n'est plus nécessaire.
Comme vous pouvez le voir, la version Guava / JDK est plus courte et évite les objets auxiliaires superflus. En cas d'égalité, cela permet même de court-circuiter l'évaluation si un Object.equals()
appel antérieur retourne false (pour être juste: commons / lang a une ObjectUtils.equals(obj1, obj2)
méthode avec une sémantique identique qui pourrait être utilisée au lieu de EqualsBuilder
permettre un court-circuit comme ci-dessus).
Donc: oui, les communes constructeurs lang sont très préférables aux construits manuellement equals()
et hashCode()
méthodes (ou ces monstres terribles Eclipse va générer pour vous), mais les versions Java 7+ / Goyave sont encore mieux.
Et une note sur Hibernate:
soyez prudent lorsque vous utilisez des collections différées dans vos implémentations equals (), hashCode () et toString (). Cela échouera lamentablement si vous n'avez pas de session ouverte.
Remarque (environ égal à ()):
a) dans les deux versions de equals () ci-dessus, vous pouvez également utiliser l'un de ces raccourcis ou les deux:
@Override
public boolean equals(final Object obj){
if(obj == this) return true; // test for reference equality
if(obj == null) return false; // test for null
// continue as above
b) en fonction de votre interprétation du contrat equals (), vous pouvez également changer la (les) ligne (s)
if(obj instanceof Bean){
à
// make sure you run a null check before this
if(obj.getClass() == getClass()){
Si vous utilisez la deuxième version, vous souhaiterez probablement également appeler super(equals())
votre equals()
méthode. Les opinions divergent ici, le sujet est discuté dans cette question:
bonne façon d'incorporer la superclasse dans une implémentation de Guava Objects.hashcode ()?
(même si c'est à peu près hashCode()
, la même chose s'applique à equals()
)
Note (inspirée du commentaire de kayahr )
Objects.hashCode(..)
(tout comme le sous-jacent Arrays.hashCode(...)
) pourrait mal fonctionner si vous avez de nombreux champs primitifs. Dans de tels cas, EqualsBuilder
peut en fait être la meilleure solution.
reflectionEquals
etreflectionHashcode
; la performance est un tueur absolu.