
인스턴스가 생성되면, 동적(힙)메모리에 메모리 공간이 생기고
인스턴스의 이름은 그 메모리를 가리키는 참조변수가 된다.
만약 두 개의 인스턴스의 주소값을 찍었을 때, 같은 값이 나온다면 같은 객체인 것이다.
1. 1. equals() 메서드 -> 저장 주소 비교
- 두 인스턴스의 주소 값(hash code,물리적인 저장 주소)을 비교하여 true/false를 반환
- 우리가 재정의 하여 두 인스턴스가 논리적으로 동일함의 여부를 구현함(hashCode()도 오버라이딩해줘야함)
- 인스턴스가 물리적으로(메모리상에서의 주소) 다르더라도, 논리적으로(인스턴스의 값) 동일한 경우 true를 반환하도록 재정의 할 수 있음
- (같은 학번, 같은 사번, 같은 아이디의 회원.... 을 유일한 키로 지정하여 hashCode값이 학번/사번/아이디로 나오게 해보자))
2. 2. hashCode() 메서드 -> 저장 주소 반환
- hashCode()는 인스턴스의 저장 주소를 반환함
- 힙메모리에 인스턴스가 저장되는 방식이 hash 방식
- hash : 정보를 저장, 검색하는 자료구조
- 자료의 특정 값(키 값)에 대한 저장 위치를 반환해주는 해시 함수를 사용

- 두 인스턴스가 같다는 것은?
- 두 인스턴스에 대한 equals()의 반환 값이 true 동일한 hashCode() 값을 반환
- 논리적으로 동일함을 위해 equals() 메서드를 재정의 하였다면 hashCode()메서드도 재정의 하여 동일한 hashCode 값이 반환되도록 한다
Student.java
<java />
package ch2;
public class Student implements Cloneable{ //클론이 가능하도록 명시
private int studentNum;
private String studentName;
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public Student(int studentNum,String studentName) {
this.studentNum=studentNum;
this.studentName=studentName;
}
public String toString() {
return studentNum+","+studentName;
}
@Override
public boolean equals(Object obj) { //equals 재정의
if (obj instanceof Student) { //다운캐스팅 하기 전에 instanceof
Student std = (Student)obj; //다운캐스팅
if(this.studentNum==std.studentNum) { //학생 번호가 같다면
return true; //true가 나오도록 재정의
}
else return false;
}
return false;
}
@Override
public int hashCode() { //hashCode 재정의
return studentNum; //주소값이 아니라 학생 번호가 나오도록 재정의
}
@Override
protected Object clone() throws CloneNotSupportedException { //clone 함수
return super.clone();
}
}

처음에 std1과 std2는 다른 객체이기 때문에, 두 결과 모두 false가 나온다.

주소는 다르지만, Student.java에서 equals를 학생 번호가 같으면 같은 객체라고 나오도록 재정의했기 때문에 true가 반환된다.

equals()로 같다는 것을 재정의했으니, std1과 std2는 같은 객체라고 판단되어
hashCode()로 두 객체의 주소값을 반환하면 같은 값이 나온다.
(그 아래 코드는 정수는 hashCode로 정수값을 반환한다는 것을 보여주는 코드)

hashCode() 또한 학생 번호를 리턴하도록 재정의하였으니,
두 객체가 같으므로(equals로 재정의) 같은 학생 번호를 리턴한다.

하지만 만약, 재정의해버린 hashCode() 메서드로는 진짜 그 객체의 hashCode값을 알 수 없다.
그렇다면
System.identityHashCode() 함수를 사용하여 각 객체의 진짜 물리적 hashCode값을 알 수 있다.
EqualsTest.java
<java />
package ch2;
public class EqualsTest {
public static void main(String[] args) throws CloneNotSupportedException {
Student std1 = new Student(100,"Lee");
Student std2=new Student(100,"Lee");
// System.out.println(std1==std2); // 주소는 다르지만,
// System.out.println(std1.equals(std2)); //논리적으로 같다는 것을 재정의했기 때문에 true 반환
//
// System.out.println(std1.hashCode()); //논리적으로 같기 때문에
// System.out.println(std2.hashCode()); //같은 hashcode값 리턴
// System.out.println(System.identityHashCode(std1)); //그렇다면 객체의 진짜 hashcode값을 알고 싶을때?
// System.out.println(System.identityHashCode(std2));
std1.setStudentName("Kim");
Student copyStudent = (Student)std1.clone(); //인스턴스의 상태를 그대로 복제 가능
System.out.println(copyStudent);
}
}
3.
4. 3. clone() 메서드
- 객체의 원본을 복제하는데 사용하는 메서드
- 생성과정의 복잡한 과정을 반복하지 않고 복제 할 수 있음(생성자는 초기값을 갖고 인스턴스가 생성되지만, 중간에 멤버변수의 값이 변한다면 변한 값 그대로 복제하는 함수임)
- clone()메서드를 사용하면 객체의 정보(멤버 변수 값등...)가 동일한 또 다른 인스턴스가 생성되는 것이므로, 객체 지향 프로그램에서의 정보 은닉, 객체 보호의 관점에서 위배될 수 있음
- 해당 클래스의 clone() 메서드의 사용을 허용한다는 의미로 cloneable 인터페이스를 명시해 줌

클론 복제해보려 했으나 오류가 발생하여, throws처리를 해주었다.

또한 Student 클래스에 clone이 가능하다고 명시해주었다.

set 메소드로 이름을 바꾼 것마저도
완전 복제해버리는 clone 메소드!
'JAVA' 카테고리의 다른 글
5-1.자료구조 (0) | 2022.02.04 |
---|---|
4-3.String, StringBuilder, StringBuffer 클래스, text block (0) | 2022.01.28 |
4-1.Object 클래스 (0) | 2022.01.26 |
3-15.객체 지향 핵심 - 여러 인터페이스 구현하기, 인터페이스의 상속 (0) | 2022.01.24 |
3-14.객체 지향 핵심 - 인터페이스의 여러가지 요소 (0) | 2022.01.24 |