package ex_object;
import java.util.*;
public class Ex2 {
public static void main(String[] args) {
/*
* 3. equals() 메서드
* - 문법 구조 : boolean equals(Object obj)
* => 파라미터로 전달된 Object 타입 객체 obj의 주소값을 자신의 주소값과 비교하여
* true 또는 flase 리턴
*
*/
// 동등비교연산자를 사용한 변수값 비교
int num1 = 10; // int형 변수 num1에 리터럴 10 저장
int num2 = 10;
// 기본 데이터타입 변수값을 비교할 때 동등비교연산자(==)를 통해 같은지를 비교
if (num1 == num2) {
System.out.println("num1, num2 같다!");
} else {
System.out.println("num1, num 다르다!");
}
// => 기본 데이터타입 변수에 같은 값을 저장할 경우 동등비교연산 결과는 true
Object obj1 = new Object(); // Object 인스턴스의 주소값을 참조변수 obj1에 저장
Object obj2 = new Object();
// => 인스턴스를 생성할 때마다 서로 다른 메모리 공간에 인스턴스가 생성되므로
// 해당 인스턴스의 주소값도 인스턴스마다 달라진다!
if (obj1 == obj2) {
System.out.println("obj1, obj2 같다!");
} else {
System.out.println("obj1, obj2 다르다!");
}
// => 따라서, obj1과 obj2의 동등비교연산 결과는 false(주소값이 다르기 때문에)
// obj1에 저장된 주소값을 Object 타입 변수 obj3에 복사할 경우
Object obj3 = obj1;
if (obj1 == obj3) {
System.out.println("obj1, obj3 같다!");
} else {
System.out.println("obj1, obj3 다르다!");
}
// => obj1과 obj3에 저장된 주소값이 동일하므로 동등비교연산 결과는 true
// equals() 메서드를 사용한 객체 비교
// 참조변수명.equals(비교할 참조변수명) 형태로 사용
// => 동등비교연산을 통한 비교 결과와 동일한 결과가 출력됨
// (내부적으로 동등비교연산자(==)를 통해 비교하게 되기 때문에)
if (obj1.equals(obj2)) {
System.out.println("obj1, obj2 같다!");
} else {
System.out.println("obj1, obj2 다르다!");
}
// 일반적으로 현실에서 두 객체가 같은가? 라는 질문은 두 객체의 주소값이 아닌
// 객체 내에 저장된 실제 데이터가 같은지를 물어보는 것이 일반적이다.
// 그러나, equals() 메서드는 두 객체의 주소값을 비교하므로
// 두 객체에 저장된 데이터가 같더라도 flase가 리턴되므로 적합하지 않다!
Person p1 = new Person("홍길동", 20);
Person p2 = new Person("홍길동", 20);
if (p1.equals(p2)) {
System.out.println("p1 과 p2가 같다!");
} else {
System.out.println("p1 과 p2는 다르다!");
}
if (p1 == p2) {
System.out.println("p1 과 p2가 같다!");
} else {
System.out.println("p1 과 p2는 다르다!");
}
System.out.println("======================================");
// equals() 메서드가 오버라이딩된 EqualsPerson 객체 비교
EqualsPerson p3 = new EqualsPerson("홍길동", 20);
EqualsPerson p4 = new EqualsPerson("홍길동", 20);
if (p3 == p4) {
System.out.println("p3과 p4의 주소값이 같다!");
} else {
System.out.println("p3과 p4의 주소값이 다르다!");
}
// EqualsPerson 클래스에 오버라이딩 된 equals() 메서드를 통한 비교
if (p3.equals(p4)) {
System.out.println("p3과 p4의 실제값이 같다!");
} else {
System.out.println("p3과 p4의 실제값이 다르다!");
}
}
}
class EqualsPerson {
String name;
int age;
public EqualsPerson(String name, int age) {
super();
this.name = name;
this.age = age;
}
// Object 클래스의 equals() 메서드 오버라이딩
// equals() 메서드 내부에서 EqualsPerson 클래스의 멤버변수를
// 파라미터로 전달된 Object 타입 객체의 멤버변수와 비교하여
// 모든 멤버변수가 같으면 true, 하나라도 다르면 false 리턴하도록 구현!
// @Override
// public boolean equals(Object obj) {
// // p1 인스턴스의 equals() 메서드 내에 p2 인스턴스가 파라미터로 전달됨
// // => 이 때, Person 타입 p2 -> Object 타입 obj로 업캐스팅 됨
//// if (age == obj.age) {} // 참조영역 축소로 인해 obj에서 age 변수가 보이지 않는다!
// // => 현재 인스턴스인 p1과 파라미터로 전달된 p2(obj)의 멤버변수를 비교해야하는데
// // 업캐스팅으로 인해 obj 변수로는 p2의 멤버변수에 접근이 불가능하다!
// // => 따라서, 다시 다운캐스팅을 통해 참조영역을 확대하면 멤버변수가 보이게 된다!
// // Object obj => Person p로 다운캐스팅
// EqualsPerson p = (EqualsPerson) obj;
//
// // int형 변수 age는 동등비교, String 타입 name은 String 클래스의 equals() 로 비교
// // => 참고! String 클래스에는 Object 클래스로부터 equals() 메서드를 상속받아
// // 문자열 내용을 비교하도록 이미 오버라이딩 되어 있다!
// if (age == p.age && name.equals(p.name)) {
// // 멤버변수 모두 같을 경우 true 리턴
// return true;
// }
//
// return false; // else 없이 true 리턴하는 조건만 정의하고 나머지는 false 리턴 가능
//
// }
// equals() 메서드 자동 오버라이딩 단축키 : Alt + Shift + S -> h
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EqualsPerson other = (EqualsPerson) obj;
return age == other.age && Objects.equals(name, other.name);
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}