Как по умолчанию .equals и .hashCode будут работать для моих классов?


106

Скажем, у меня есть собственный класс

public class MyObj { /* ... */ }

У него есть некоторые атрибуты и методы. Он НЕ реализует равенства, НЕ реализует hashCode.

Каковы реализации по умолчанию после вызова equals и hashCode? Из класса объекта? А какие они? Как будет работать равенство по умолчанию? Как будет работать хэш-код по умолчанию и что вернет? == просто проверит, ссылаются ли они на один и тот же объект, так что это просто, но как насчет методов equals () и hashCode ()?

Ответы:


94

Да, реализация по умолчанию - это Object (вообще говоря, если вы наследуете от класса, который переопределил equals и / или hashCode, то вместо этого вы будете использовать эту реализацию).

Из документации:

equals

Метод equals для класса Object реализует наиболее различающее возможное отношение эквивалентности для объектов; то есть для любых ненулевых ссылочных значений x и y этот метод возвращает true тогда и только тогда, когда x и y относятся к одному и тому же объекту (x == y имеет значение true).

hashCode

Насколько это разумно практично, метод hashCode, определенный классом Object, действительно возвращает отдельные целые числа для отдельных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но этот метод реализации не требуется для языка программирования JavaTM.)


50

Из Objectодной из реализаций JVM:

public boolean equals(Object object) {
    return this == object;
}

public int hashCode() {
    return VMMemoryManager.getIdentityHashCode(this);
}

В обоих случаях это просто сравнение адресов памяти рассматриваемых объектов.


7
Какая версия JDK это от? In v6u23 ea:public native int hashCode();
— хачик

@kha - Вы правы, я думаю, что нашел одну из нативных реализаций, чтобы посмотреть, что она на самом деле сделала
— Брэд Мейс

10

Существуют реализации по умолчанию equals()и hashCode()в Object. Если вы не предоставите свою собственную реализацию, они будут использоваться. Ибо equals()это означает ==сравнение: объекты будут равны, только если они являются одним и тем же объектом. Ибо hashCode()у Javadoc есть хорошее объяснение.

Для получения дополнительной информации см. Эффективная Java, Глава 3 (pdf), пункт 8.


1

Да, из Objectкласса, поскольку ваш класс неявно расширяет Object. equalsпросто возвращается this == obj. hashCodeреализация родная. Угадайте - возвращает указатель на объект.


2
Это указатель на объект, расположенный в памяти, но не адрес объекта в памяти. GC может перемещать объект в памяти, и хэш-код останется прежним.
— Джереми

@ Джереми Спасибо. stackoverflow.com/questions/2427631/… может быть интересным.
— хачик

1

Если вы не предоставите свою собственную реализацию, будет использоваться реализация, производная от Object. Это нормально, если вы не планируете помещать экземпляры класса, например, в HashSet (любую коллекцию, которая фактически использует hashCode ()) или что-то, что необходимо для проверки равенства объектов (например, метод HashSet contains ()). В противном случае он будет работать неправильно, если вы об этом просите.

Довольно легко предоставить собственную реализацию этих методов благодаря HashCodeBuilder и EqualsBuilder от Apache Commons Lang .


(a) Почему вы говорите, что реализация equals класса Object по умолчанию не будет правильно работать с HashSet? Это противоречит другим ответам на этой странице. (б) Спасибо за ссылки Commons Lang.
— Basil Bourque

1
@Basil: Не думаю, что это противоречит. Конечно, реализация по умолчанию будет работать ... как-то, но не так, как вы ожидаете. То есть, поскольку equals () использует ссылочное равенство, два идентичных объекта в противном случае будут «разными» с точки зрения реализации по умолчанию. В результате у вас может оказаться два разных экземпляра одного и того же объекта в вашем Set. И довольно типичное использование Наборов - это когда вы хотите удалить дубликаты ...
— Павел Дида

@ PawełDyda: поведение по умолчанию обычно правильно для изменяемых типов. Если Fooи Barявляются ссылками на два разных экземпляра изменяемого типа, и существует метод (например SomeMutatingMethod), который Foo.SomeMutatingMethod()не влияет так Barже, как он Foo, это различие должно быть достаточным, чтобы рассматривать объекты как неравные.
— supercat

0

IBM developerworks говорит:

В этой реализации по умолчанию две ссылки равны, только если они относятся к одному и тому же объекту. Точно так же реализация hashCode () по умолчанию, предоставляемая Object, получается путем сопоставления адреса памяти объекта с целочисленным значением.

Однако, чтобы быть уверенным в точных деталях реализации версии Java конкретного поставщика, вероятно, лучше всего посмотреть в качестве источника (если он доступен)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.