添加 equals() 和 hashCode() 方法会破坏某些东西吗
Can adding equals() and hashCode() method spoil something
添加 equals()
和 hashCode()
方法是否可能会破坏现有代码?
我有一个 class 有 3 个字段,getter 和 setter:
public class Person {
private final String name;
private final List<Friend> friends;
private final Integer age;
为了测试这个 class 我使用了:isEqualToComparingFieldByField()
方法来比较两个 Person
对象而不是添加 equals()
和 hashCode()
。其他解决方案是覆盖 equals()
和 hashCode()
并使用 assertEquals()
来比较这些对象,但我能完全确定它不会破坏任何东西吗?
Can I be totally sure that it won't break anything?
没有。您正在将相等的含义从引用标识更改为某种值相等。你会破坏任何依赖于当前行为的东西。例如,这里有一些有效代码:
Person person1 = new Person("Foo", 100);
Person person2 = new Person("Foo", 100);
// This is fine. Two distinct Person objects will never be equal...
if (person1.equals(person2)) {
launchNuclearMissiles();
}
您提议的更改会打破这一点。
你真的有这样的代码吗?不好说。
更有可能的是,如果您想更改 hashCode
以包含来自 List<Friend>
的散列,您可能很容易破坏代码,除非该类型实际上是不可变的。例如:
Map<Person, String> map = new HashMap<>();
Person person = new Person("Foo", 100);
map.put(person, "Some value");
// If this changes the result of hashCode()...
person.addFriend(new Friend("Bar"));
// ... then you may not be able to find even the same object in the map.
System.out.println(map.get(person));
从根本上说,您需要了解其他代码使用了什么 Person
,这样您就知道它依赖什么。如果 Person
是不可变的,那会使生活 简单得多 因为你不需要担心第二种问题。 (为可变类型覆盖 equals()
和 hashCode()
从根本上讲是一项危险的工作。)
这取决于您在哪里以及如何使用人物对象。例如,如果你将 person 存储在 HashSet、HashMap 等数据结构中,那么它的行为可能会有所不同。但是,如果您使用任何使用散列和等于的数据结构,始终建议覆盖这些方法。
您在创建自定义 class 时应始终重写这些方法。如果您不这样做,那么将使用对象 class 的实现,并且这些实现依赖于引用 - 而不是自定义对象 class.
中的字段值
如果您创建两个相同的自定义对象 class 并使用对象 class 中的 equals() 方法来比较它们,您将得到 'false' 结果。那是因为即使这些对象相同,它们包含不同的引用。
添加 equals()
和 hashCode()
方法是否可能会破坏现有代码?
我有一个 class 有 3 个字段,getter 和 setter:
public class Person {
private final String name;
private final List<Friend> friends;
private final Integer age;
为了测试这个 class 我使用了:isEqualToComparingFieldByField()
方法来比较两个 Person
对象而不是添加 equals()
和 hashCode()
。其他解决方案是覆盖 equals()
和 hashCode()
并使用 assertEquals()
来比较这些对象,但我能完全确定它不会破坏任何东西吗?
Can I be totally sure that it won't break anything?
没有。您正在将相等的含义从引用标识更改为某种值相等。你会破坏任何依赖于当前行为的东西。例如,这里有一些有效代码:
Person person1 = new Person("Foo", 100);
Person person2 = new Person("Foo", 100);
// This is fine. Two distinct Person objects will never be equal...
if (person1.equals(person2)) {
launchNuclearMissiles();
}
您提议的更改会打破这一点。
你真的有这样的代码吗?不好说。
更有可能的是,如果您想更改 hashCode
以包含来自 List<Friend>
的散列,您可能很容易破坏代码,除非该类型实际上是不可变的。例如:
Map<Person, String> map = new HashMap<>();
Person person = new Person("Foo", 100);
map.put(person, "Some value");
// If this changes the result of hashCode()...
person.addFriend(new Friend("Bar"));
// ... then you may not be able to find even the same object in the map.
System.out.println(map.get(person));
从根本上说,您需要了解其他代码使用了什么 Person
,这样您就知道它依赖什么。如果 Person
是不可变的,那会使生活 简单得多 因为你不需要担心第二种问题。 (为可变类型覆盖 equals()
和 hashCode()
从根本上讲是一项危险的工作。)
这取决于您在哪里以及如何使用人物对象。例如,如果你将 person 存储在 HashSet、HashMap 等数据结构中,那么它的行为可能会有所不同。但是,如果您使用任何使用散列和等于的数据结构,始终建议覆盖这些方法。
您在创建自定义 class 时应始终重写这些方法。如果您不这样做,那么将使用对象 class 的实现,并且这些实现依赖于引用 - 而不是自定义对象 class.
中的字段值如果您创建两个相同的自定义对象 class 并使用对象 class 中的 equals() 方法来比较它们,您将得到 'false' 结果。那是因为即使这些对象相同,它们包含不同的引用。