在使用Lombok的@Data注解时,对于继承关系,需要注意equals和hashCode方法的实现。

151
我有一个继承自其他类的实体。另一方面,我正在使用Lombok项目来减少样板代码,所以我加了@Data注解。使用继承的@Data注解会产生以下警告:
生成equals/hashCode实现,但没有调用父类,尽管该类并没有继承java.lang.Object。如果这是有意的,请在您的类型上添加@EqualsAndHashCode(callSuper=false)。
我有以下问题:
1. 是否建议添加@EqualsAndHashCode(callSuper = true)或@EqualsAndHashCode(callSuper = false)注解? 2. 如果不添加注解,是哪一个:callSuper=false还是callSuper=true?
4个回答

165

默认值false。如果您不指定它并忽略警告,那么就会得到这个默认值。

是的,建议在使用@Data注释的类继承其他类而非Object时添加@EqualsAndHashCode注释。我无法告诉您需要true还是false,这取决于您的类层次结构,并且需要逐个案例进行检查。

但是,对于一个项目或包,您可以在lombok.config中配置,如果它不是直接从Object子类化,则调用超级方法。

lombok.equalsAndHashCode.callSuper = call

请参阅配置系统文档以了解其工作原理,以及@EqualsEndHashCode文档以获取支持的配置键信息。
披露:我是lombok开发人员。

对我有用。但请记住,为了delombok插件能够捕获此配置文件,它应该放在Java源代码根目录中而不是资源目录中,即在src/main/java而不是src/main/resources中。 - Alok P
3
@Roel,我在想为什么默认值是false。我本来期望相反的结果。另外,是否有一种等效的方法可以使toString()默认调用super?我看到可以使用“@ToString(callSuper=true)”,但没有看到任何这样的配置设置。谢谢。 - David Siegal
1
在@Data之前或之后添加@EqualsAndHashCode(callSuper=true)是否重要? - Anna Klein
1
@AnnaKlein 顺序无关紧要 - dan carter

66

@EqualsAndHashCode(callSuper=true) 应该解决警告。


2
这应该是被接受的答案,因为我认为不应该像Roel建议的那样做“lombok.equalsAndHashCode.callSuper = call”,而是应该针对每个类做出决定。 - Anna Klein
9
@AnnaKlein 我不这样认为。实际上,这个答案应该是一条评论,因为它没有提供新的信息,而且你可以在我的问题中找到那个信息。我确实知道 @EqualsAndHashCode 可以解决这个警告。 - Pau
实际上,根据被接受的答案(以及我下面的答案),您应该在注释中选择'callSuper=true'或'callSuper=false'之间进行选择。 - Adam Wise

51
主要的原始问题是:
是否建议添加注释@EqualsAndHashCode(callSuper =   true)或@EqualsAndHashCode(callSuper = false)?
接受的答案基本上只是:
那取决于......
为了进一步扩展,@EqualsAndHashCode文档提供了一些可靠的指导,可以选择哪种。 尤其是这个,在我看来:
通过将callSuper设置为true,您可以在生成的方法中包含超类的equals和hashCode方法。对于hashCode,super.hashCode()的结果包含在散列算法中,而对于equals,如果super实现认为它与传递的对象不相等,则生成的方法将返回false。请注意,并非所有equals实现都正确处理此情况。但是,lombok生成的equals实现确实正确处理了这种情况,因此,如果您的超类也有一个由lombok生成的equals方法,则可以安全地调用其超类equals。
简化一下:
如果您继承自没有状态信息的超类,或者超类本身正在使用@Data注释,或者具有“正确处理情况”的equals / hash实现(我解释为返回状态值的正确哈希),则选择'callSuper = true'。

4
我认为这个答案很好地解释了如何在callSuper = false和callSuper = true之间做出选择。 - prageeth
1
我同意。这个解释真的很有帮助。 - Kira Resari

29
如果您想要比较超类的成员,可以使用@EqualsAndHashCode(callSuper=true)。然而,如果只想要比较当前类的字段,可以使用@EqualsAndHashCode(callSuper=false),这是默认选项。
如果您使用Delombok功能,您可以看到当设置为true时,以下行将添加到生成的equals方法中:if (!super.equals(o)) return false;。如果超类中有成员需要在比较两个对象时考虑,则必须将其设置为true以正确比较。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接