Java에서 equals()를 작성하는 방법
이 기사의 끝에서 Java 프로그래밍 언어로 최고의 equals() 메소드를 작성하는 데 필요한 모든 정보를 다룰 것입니다. equals () 메서드의 모범 사례를 사용하는 데 필요한 기본 정보를 다루기 위해 수학적 정의와 Java 프로그래밍 언어의 방식으로 평등에 대한 세부 사항을 다룰 예정입니다 .
평등의 수학적 정의
Wikipedia 에 따르면 수학적 평등의 정의는 다음과 같습니다.
수학에서 등식은 두 수량 또는 더 일반적으로 두 수학적 표현 사이의 관계로, 수량은 동일한 값을 갖거나 표현이 동일한 수학적 대상을 나타낸다고 주장합니다. A 와 B 사이의 평등은 A = B 로 쓰여지고 A 가 B 와 같다고 발음됩니다 .
Java의 평등 정의
Java 프로그래밍 언어에서 동등성은 단순히 동일한 값을 갖는 것을 의미합니다. 문자 그대로 같은 값을 가지는 것을 의미하기도 하고, 객체의 속성에 있어서도 같은 구조를 가지는 것을 의미하기도 합니다.
두 개의 기본 타입 값이 같은지 확인해야 할 경우 아래 예와 같이 등호를 직접 사용한다.
int a = 5;
int b = 6;
int c = 5;
// Prints "false" since a and b do not have the same value.
System.out.println(a == b);
// Prints "true" since a and c have the same value.
System.out.println(a == c);
반면에 두 개체의 동등성을 확인해야 하는 경우도 있습니다. 개체와 관련하여 두 개체의 동등성을 확인하는 프로세스의 다른 단계에서 사용되는 두 가지 접근 방식이 있습니다. 자세한 내용을 살펴보겠습니다.
참조 평등
Java 프로그래밍 언어에서 객체의 실제 값은 메모리 어딘가에 저장되며 메모리 어딘가에 저장되어 있는 객체 참조에 의해 지정됩니다. 다음 코드 스니펫을 살펴보겠습니다.
// Create an object with "new" operator.
// Point to object with object reference "a".
Object a = new Object();
// Create another object reference.
// Point to the same object as the reference "a" is pointing.
Object b = a;
// Output is true.
System.out.println(a == b);
// Create another object with "new" operator.
// Point to object with object reference "b".
b = new Object();
// Output is false.
System.out.println(a == b);
이러한 시나리오에서 "a"와 "b"는 실제로 동일한 개체를 가리키는 두 개의 참조이므로 "a"는 "b"와 같다고 직접적으로 말할 수 있습니다.
그러나 반대 시나리오가 항상 유효한 것은 아닙니다. 두 개의 서로 다른 참조가 서로 다른 메모리 위치를 가리킬 수 있지만 참조가 가리키는 개체는 여전히 동일할 수 있습니다.
정상적인 삶에서는 때때로 양을 비교합니다. 당신이 두 개의 사과를 가지고 있고 당신의 친구가 두 개의 사과를 가지고 있다면 당신과 당신의 친구가 가진 사과의 수는 같습니다.
한편, 때로는 사물의 속성이나 구조로 비교되기도 합니다. 이 시나리오에 대한 자세한 내용을 살펴보겠습니다.
구조적 평등
구조적 동등성은 속성의 상태에 따라 객체가 비교되는 유형입니다. 이러한 유형의 동등성을 확인하려면 "==" 연산자만이 아닌 보다 정교한 도구가 필요합니다. equals() 메서드입니다. Java 프로그래밍 언어에서 클래스 계층 구조의 가장 높은 지점에 있는 Object 클래스에서 가져옵니다. 곧 출시될 자바 코드 스니펫을 확인해 봅시다.
public class Car {
// Assume that we have corresponding constructor, accessors, mutators, etc.
private String brand;
private String model;
private Integer modelYear;
private Integer mileage;
}
Car car1 = new Car("Audi","R8", 2023);
Car car2 = new Car("Audi","R8", 2023);
Car car3 = new Car("Audi","R8", 2021);
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car3));
public boolean equals(Object obj) {
return (this == obj);
}
public class Car {
private String brand;
private String model;
private Integer modelYear;
private Integer mileage;
// Assume that we have corresponding constructor, accessors, mutators, etc.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear);
}
}
두 번째 줄에서 개체의 ID를 확인하기 시작합니다. 개체 참조 o 가 null이거나 두 개체 참조가 서로 다른 클래스에 속하는 개체를 가리키는 경우 이 두 개체가 동일한 ID를 갖지 않으며 동일하지 않다고 직접 말할 수 있습니다. 그렇지 않은 경우 마침내 개체의 실제 구조를 확인할 수 있습니다.
메서드의 세 번째 줄에서 해당 메서드가 Object 클래스에서 재정의되고 이제 Car 클래스에 속한다는 것을 알고 있으므로 참조 o를 해당 클래스 유형으로 캐스팅합니다.
마지막으로 메서드의 마지막 줄에서 두 개체의 구조를 확인하고 ID를 정의하는 실제 줄입니다. 간단히 말해, 브랜드 모델과 연식이 같다면 이 두 개체는 동일합니다. 다시 말해 구조적 평등이다.
우리는 초등학교에서 수학적 평등의 속성을 배웠습니다. 이러한 속성 중 일부는 equals() 메서드 에도 유효해야 합니다 . 이는 equals() 메서드 의 구성 요소에 이러한 속성을 추가해야 함을 의미합니다 . 수학적 등식과 Java의 등식 측면에서 이러한 속성을 살펴보겠습니다.
반사 속성
반사 속성의 수학적 정의에서 모든 실수에 대해 x ;
엑스 = 엑스
숫자는 자신과 같습니다.
Java 동등성 측면에서 객체는 자신과 같아야 합니다.
Car car1 = new Car("Audi","R8",2013);
System.out.println(car1.equals(car1));
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return mileage < car.mileage && brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear);
}
대칭 속성
대칭 속성의 수학적 정의 측면에서 모든 실수 x 및 y 에 대해 ;
x = y 이면 y = x
평등의 순서는 중요하지 않습니다.
Java 동등성 측면에서 객체 a가 객체 b와 같으면 객체 b는 객체 a와 같아야 합니다.
Car car1 = new Car("Audi","R8",2013);
Car car2 = new Car("Audi","R8",2013);
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car1));
public class Car {
private String brand;
private String model;
private Integer modelYear;
private Integer mileage;
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Car)) return false;
Car car = (Car) o;
return brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear);
}
}
public class SportCar extends Car {
private String engineType;
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof SportCar)) return false;
SportCar sportCar = (SportCar) o;
return engineType.equals(sportCar.engineType);
}
}
Car car1 = new Car("Audi", "R8", 2012, 1000);
SportCar car2 = new SportCar("Audi", "R8", 2012, 1000, "4.0");
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car1));
전이 속성
전이 속성의 수학적 정의에서 모든 실수 x , y 및 z 에 대해 ;
x = y 및 y = z 이면 x = z
같은 수와 같은 두 수는 서로 같습니다.
Java 동등성 측면에서 개체 a가 개체 b와 같고 개체 b가 개체 c와 같으면 개체 a는 개체 c와 같아야 합니다.
SportCar car1 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("100RPM"));
Car car2 = new Car("Audi", "R8", 2012, 1000);
SportCar car3 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("101RPM"));
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car3));
System.out.println(car1.equals(car3));
public class SportCar extends Car {
private Turbo turbo;
@Override
public boolean equals(Object o) {
if (!(o instanceof Car)) return false;
if (!(o instanceof SportCar)) return o.equals(this);
return super.equals(o) && ((SportCar) o).turbo == turbo;
}
}
public class Turbo {
private String power;
public Turbo(String power) {
this.power = power;
}
}
SportCar car1 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("100RPM"));
Car car2 = new Car("Audi", "R8", 2012, 1000);
SportCar car3 = new SportCar("Audi", "R8", 2012, 1000, new Turbo("101RPM"));
System.out.println(car1.equals(car2));
System.out.println(car2.equals(car3));
System.out.println(car1.equals(car3));
일관된 속성
이것은 수학적으로 정확히 일치하는 것이 없기 때문에 다른 속성입니다. 이를 위해 우리는 equals() 메소드의 연속 실행에 대해 동일한 결과를 얻어야 합니다.
아래 코드 스니펫을 살펴보겠습니다.
Car car1 = new Car("Audi", "R8", 2012, 1000);
Car car2 = new Car("Audi", "R8", 2012, 1000);
for (int i = 0; i < 100000; i++) {
System.out.println(car1.equals(car2));
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Car)) return false;
Car car = (Car) o;
Random random = new Random();
return brand.equals(car.brand) && model.equals(car.model) && (random.nextInt(10) + 2013) == car.modelYear;
}
참고: 이 예는 저를 만족시키지 못합니다. 광범위한 조사 후 더 나은 것으로 교체하겠습니다. equals() 메서드의 Java 문서에서 " 일관되게 반환 하거나 지속적으로 반환하는 다중 호출 "이라고 명확하게 설명되어 있습니다. 이 진술에 대한 확실한 위반 사례가 있어야 합니다.x.equals(y)truefalse
Null 매개변수 속성
이것이 내가 이 속성을 호출하기로 선택한 방법입니다.
아래 코드 스니펫을 살펴보십시오.
Car car1 = new Car("Audi", "R8", 2012, 1000);
Car car2 = null;
System.out.println(car1.equals(car2));
이제 동등성에 대한 올바른 계산을 제공하기 위해 equals() 메서드 구현에 어떤 속성이 있어야 하는지 명확합니다. 또한 가능한 위반 시나리오를 보았으므로 이제 코드 품질 및 비즈니스 논리를 위해 이러한 위반을 피할 수 있습니다.
오늘날 많은 IDE는 가능한 최상의 equals() 메서드 구현을 생성하기 위한 생성 메커니즘을 제공합니다. equals() 메서드 를 구현하는 대신 대부분의 시간을 고수하는 것이 좋습니다 . Intellij IDEA 의 예를 살펴보겠습니다 .
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return brand.equals(car.brand) && model.equals(car.model) && modelYear.equals(car.modelYear) && mileage.equals(car.mileage);
}
두 개체 참조가 동일한 개체를 가리킬 수 있기 때문에 첫 번째 줄에서 참조 동등성을 확인합니다.
두 번째 줄에서는 Null Parameter Property 의 유효성 검사 가 보장되며 Transitive Property 및 Symmetric Property 위반을 방지하기 위해 참조가 가리키는 객체의 클래스 유형을 제어하여 동일한 if 조건이 가드 if 절 역할을 합니다. .
세 번째 줄에서 개체 참조는 Car 개체의 속성에 도달하기 위해 이 예제에서 Car인 해당 클래스 유형으로 캐스팅됩니다.
마지막으로 네 번째 줄에서는 구조적 동등성 측면에서 동등성을 확인합니다.
equals() 메서드 생성을 위한 다른 템플릿이 있습니다 . 가셔서 확인하셔도 됩니다.
직접 구현을 작성하려면 구현이 모든 equals() 메소드 속성에 대한 유효성을 보장해야 한다는 점을 명심하십시오.
기사의 끝 부분에 이르렀지만 여전히 다루어야 할 매우 중요한 격차가 있습니다. IDE를 열고 equals() 메서드를 생성해 봅니다 . hashCode() 메서드 없이 equals() 메서드 만 생성하는 옵션이 없다는 것을 알게 될 것입니다 . Java 프로그래밍 언어의 일부 컬렉션 유형으로 인해 이 두 메서드를 서로 분리하지 않는 것이 좋습니다. 또한 공식 Java 문서에는 equals() 메서드가 재정의될 때마다 일반적으로 hashCode() 메서드 를 재정의해야 한다고 명시되어 있습니다 . 내 다른 기사에서 해싱 및 hashCode() 메서드 에 대한 해당 정보를 제공하고 싶습니다 .
또한 때로는 JPA의 엔티티 클래스와 같은 일부 예외적인 경우에 equals() 메서드 속성을 고수하지 않아도 될 수도 있습니다 . 또한 자체 기사가 필요합니다.
결론적으로
올바른 equals() 메서드를 구현하기 위한 모든 중요한 사항은 이 문서에서 다룹니다. 또한 equals() 메서드 속성 의 유효성 검사를 테스트하기 위해 해당 단위 테스트를 작성하는 것이 좋습니다 . 웹에서 찾을 수 있는 다른 리소스를 살펴보는 것을 잊지 마십시오.
일단 객체지향 설계의 기초부터 다루기 때문에 굉장히 쉽고 원시적인 주제인 것 같습니다. 그러나 세부 사항에서 알 수 있듯이 이러한 기본 개념을 건너 뛰지 않고 완전히 이해하는 것이 매우 중요합니다.

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































