Burninghering's Blog
article thumbnail

인스턴스가 생성되면, 동적(힙)메모리에 메모리 공간이 생기고

인스턴스의 이름은 그 메모리를 가리키는 참조변수가 된다.

 

만약 두 개의 인스턴스의 주소값을 찍었을 때, 같은 값이 나온다면 같은 객체인 것이다. 

 

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 메소드!

profile

Burninghering's Blog

@개발자 김혜린

안녕하세요! 반갑습니다.