Java에서 equals() 및 hashCode() 메서드 재정의
Equals
hashCode
클래스에 선언되고 Object
표준 Java 라이브러리에 포함된 기본 메서드 입니다 . 이 방법은 еquals()
객체를 비교하고 hashCode
객체에 대한 정수 코드를 생성하는 데 사용됩니다. 이러한 메소드는 NET에서 객체를 삽입하고 검색할 때 Java 표준 라이브러리에서 널리 사용됩니다 HashMap
. 이 메서드는 또한 개체를 비교해야 하는 다른 경우뿐만 아니라 다른 구현 에서는 equal
고유한 개체만 저장되도록 하는 데에도 사용됩니다 . 클래스에 있는 메서드의 기본 구현은 변수가 저장하는 메모리 주소에 대한 참조를 비교하고 주소가 일치하는 경우에만 반환합니다. 즉, 변수는 동일한 개체를 참조합니다. Java에서는 자연스러운 논리나 비즈니스 논리에 따라 비교가 수행되기를 기대하는 경우 및 메서드를 재정의할 것을 권장합니다. 표준 Java 라이브러리의 많은 클래스는 이를 재정의합니다. 예를 들어 클래스는 비교되는 두 개체의 내용이 동일한 경우 반환되도록 재정의합니다 . 래퍼 클래스는 수치 비교 등을 수행하는 메서드를 재정의합니다. Java는 및 메소드 를 사용하여 과 를 비교 하므로 Java는 이러한 메소드를 대체하기 위해 다음 규칙을 제공합니다. HashSet
Set
equals()
java.lang.Object
true
equals()
hashCode()
String
equals
true
Integer
equal
HashMap
HashTable
equals()
hashCode()
key
values
- 재귀성: 객체는 자신과 동일해야 합니다.
- 대칭:
a.equals(b)
을 반환 하면true
도b.equals(a)
반환해야 합니다true
. - 전이성:
a.equals(b)
반환true
하고b.equals(c)
또한 반환하는true
경우c.equals(a)
또한 반환해야 합니다true
. - 일관성: 메소드에 대한 반복 호출은
equals()
객체의 속성 값 중 일부가 변경되지 않는 한 동일한 값을 반환해야 합니다. 즉, Java에서 두 객체가 동일하면 해당 속성이 변경되지 않는 한 동일합니다. - 비교
null
: 개체를 확인해야 합니다null
. 개체가 와 같으면null
메서드는false
가 아닌 을 반환해야 합니다NullPointerException
. 예를 들어,a.equals(null)
를 반환해야 합니다false
.
Java의 equals와 hashCode 간의 일치
- 메소드 실행 결과에서 객체가 동일하면 동일해야 합니다
equals
.hashcode
- 메소드 실행 결과에서 객체가 동일하지 않으면 동일하거나 다를 수 있습니다
equals
.hashcode
그러나 성능을 향상시키려면 서로 다른 개체가 서로 다른 코드를 반환하도록 하는 것이 좋습니다.
Java에서 같음 메소드를 재정의하는 방법
-
@Override public boolean equals(Object obj) { /*1. Check*/
if (obj == this) { /*and return */ return true; }
-
Проверьте an object на
null
, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощьюinstanceof
так How такая проверка будет возвращатьtrue
для подклассов и будет работать правильно только в случае если ваш класс объявлен Howimmutable
. Вместо этого можно использоватьgetClass()
;if (obj == null || obj.getClass() != this.getClass()) { return false; }
-
Объявите переменную типа, который вы сравниваете, и приведите
obj
к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемыеshort-circuit logical operators
) для объединения проверок с другими атрибутами.Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName .equals(guest.getLastName()))); }
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
private int id;
private String firstName;
private String lastName;
public int getId() { return id; }
public void setId(int id) { this.id = id;}
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Person guest = (Person) obj;
return id == guest.id
&& (firstName == guest.firstName
|| (firstName != null &&firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName
|| (lastName != null && lastName .equals(guest.getLastName())
));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + id; result = prime * result +
((lastName == null) ? 0 : lastName.hashCode()); return result;
}
}
Распространенные ошибки при переопределении equals в Java
-
Вместо того, чтобы переопределять метод
equals (Override)
программист перегружает его(Overload)
Синтаксис методаequals()
в классеObject
определен Howpublic boolean equals(Object obj)
, но многие программисты ненароком перегружают метод:public boolean equals(Person obj)
- instead ofObject
в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-заstatic binding
. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, напримерArrayList
и вызовете методcontains()
, работа которого основана на методеequals()
, то методcontains
не сможет обнаружить ваш an object. -
При переопределении метода
equals()
не проверять наnull
переменные, что в конечном итоге заканчиваетсяNullPointerException
при вызовеequals()
. Ниже представлен корректный code.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Третья распространенная ошибка это не переопределять метод
hashCode()
, а толькоequals()
. Вы обязаны переопределять оба методаequals()
иhashCode()
в Java. МетодhashCode
используется вhash
-коллекциях(напримерHashSet
), и чем меньше будет коллизий (одинаковый code при разных an objectх) тем эффективнее эти коллекции будут работать с an objectми вашего класса. -
Последняя распространенная ошибка программистов в том, что при переопределении метода
equals()
не сохраняется соответствие между методамиequals()
иcompareTo()
, что является неформальным требованием для избежания хранения дубликатов вSet (SortedSet, TreeSet)
.
Подсказки How писать в Java метод equals
-
Большинство IDE такие How NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов
equals()
иhashCode()
. В Eclipse нажмите правую кнопку -> source ->generate equals()
иhashCode()
. -
Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на equalsство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.
-
При переопределении
hashCode()
в Java удостоверьтесь в использовании всех полей, что были использованы в методеequals()
. -
String
및 와 같은 래퍼 클래스는Integer
메서드 를 재정의Float
하지만 재정의 하지는 않습니다.Double
equals()
StringBuffer
-
가능하다면 Java에서 변수를
immutable
사용하여 필드를 만드세요final
. -
String
객체를 비교할 때는equals()
대신 .연산자를 사용하세요==
. -
논리적으로 동일하지만 다른 객체에서 로드된 두 객체는
ClassLoader
동일할 수 없습니다. 로더 클래스가 다른 경우 로 확인하면 결과getClass()
가 반환된다는 점을 기억하세요.false
-
@Override
.메서드에도 주석을 사용하면hashCode
의 반환 값과 같은 미묘한 오류를 방지할 수int
있지만 일부 프로그래머는 를 반환합니다long
.
GO TO FULL VERSION