Почему класс ProcessBuilder не переопределяет equals()?
Недавно я обнаружил, что класс ProcessBuilder в JDK6 не переопределяет equals()
, Есть ли причина? Поскольку класс изменчив, я могу понять, почему он не переопределяет hashCode()
,
Я был удивлен, увидев, что этот код не работает:
ProcessBuilder x = new ProcessBuilder("abc", "def");
ProcessBuilder y = new ProcessBuilder("abc", "def");
if (x.equals(y)) { // they are never equal
// something important here
}
Я посмотрел в исходный код JDK6 для класса ProcessBuilder
и я не вижу переопределения для equals()
,
У меня есть ощущение, что есть более глубокая причина, помимо этого одного класса. Возможно, это намеренно?
2 ответа
В дополнение к ответу @PeterLawrey: для объектов, которые изменчивы по своей природе, реализация equals и hashcode рискованна в любом случае. Вы не гарантируете, что такие объекты безопасно опубликованы вообще. Поэтому имеет смысл, что авторы таких классов просто "отказались" от равенства и хэш-кода для таких классов.
ОДНАКО: если вы достаточно уверены, что можете контролировать это равенство, то для вас есть что-то: Guava'sEquivalence
, Если вы можете обеспечить достаточно контролируемый доступ к сильно изменяемым классам, это позволит вам определить стратегию равенства / хэш-кода для таких объектов, чтобы вы могли даже использовать их, скажем, в HashSet
,
Подробнее об этом Equivalence
: для "нестабильного" класса X
который является изменчивым по своей природе, но для которого вы можете гарантировать эквивалентность в данном контексте, вы реализуете Equivalence<X>
, Затем вы "оберните" эти случаи X
например, в:
Set<Equivalence.Wrapper<X>>
Затем вы добавите в этот набор, используя:
set.add(eq.wrap(x));
где eq
ваша реализация Equivalence
,
Лучше всего делать изменяемые объекты не равными, если они не являются одним и тем же объектом. Это потому, что объект может измениться позже. Рассмотрим следующее
Set<ProcessBuilder> pbSet = new HashSet<>();
pbSet.add(x);
pbSet.add(y);
// if x and y were equal pbSet would have one element.
y.setSomething()
// should pbSet have one or two elements.
Хуже, чем это противоположный случай, когда два объекта могут быть разными, но позже сделаны одинаковыми. Это означает, что у Set будет дублированный объект.
Интересно то, что коллекции изменчивы, но все еще имеют equals и hashCode. Я думаю, что причина этого в том, что нет неизменных коллекций. например, переопределение строки равно (), StringBuilder нет.