[Java] Object Class 탐구하기

?에서 !로·2021년 8월 8일
0

Java

목록 보기
2/2

우리는 코딩을 할때 클래스를 생성하거나 import 하여 사용합니다. 이러한 클래스들은 상속과 인터페이스를 통해 서로 이어져 있습니다. 그렇다면 과연 계속 위로 올라가다 보면 가장 위에는 무엇이 존재할까? 라는 의문이 생겼습니다. 이러한 질문의 답을 줄수 있는 것은 바로 Object 클래스 입니다. 이제 Object 클래스에 대해 한번 알아보겠습니다.

java.lang.Object


Java의 lang 패키지는 Java 프로그래밍에 필요한 가장 기본적인 클래스들이 모여있는 패키지입니다. lang 패키지에 포함되는 클래스는 import구문 없이도 컴파일러에 의해 자동으로 프로그램에 포함됩니다. 그래서 System이나 String 클래스를 아무런 import 없이 사용할 수 있는 것입니다.

이러한 모든 클래스들이 상속받는 최상위 클래스가 Object 클래스 입니다. Object 클래스는 명시적으로 상속하지 않아도 모든 클래스를 자동으로 상속합니다. 즉 저희가 막 생성한 Class에 아무것도 작성되어 있지않아도 보이지 않게 Object Class를 상속 받고 있는 것입니다.

따라서 모든 클래스에서 Object클래스의 메소드를 바로 사용할 수 있고 총 11개의 메소드 만으로 구성되어 있습니다.
이제 이러한 Object 클래스의 메소드에 대해 알아보겠습니다.

Object Method


  • Object clone() : 원본 객체의 필드값과 동일한 값을 가지는 새로운 객체를 생성
@AllArgsConstructor
@ToString
@Setter
class Matrix implements Cloneable{
    String name;
    int nums;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {

        Matrix agent1 = new Matrix("Smith",1);
        Matrix agent2 = (Matrix)agent1.clone();
        System.out.println(agent2);
    }
}

복제할 객체의 클래스에는 Clonable 인터페이스를 명시해야 합니다.

  • String toString() : 객체가 가지고 있는 정보나 값을 문자열로 만들어 리턴
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

정의된 toString은 Class의 이름과 hash주소값을 리턴합니다. 그래서 toString은 해당 클래스에 재정의 하여 사용하는 것을 권장합니다.

@Override
    public String toString() {
        return "Matrix{" +
                "name='" + name + '\'' +
                ", nums=" + nums +
                '}';
    }

하지만 toString()을 재정의 하지 않아도 자동으로 제공하는 경우가 있는데 다음과 같습니다.

  1. 정적 유틸리티 클래스
  2. enum 타입 클래스
  • Boolean equals(Object obj) : 두 객채가 동일한지 검사하여 Boolean 값을 return
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

Object 클래스에 기본적으로 명시된 equals 함수는 == 논리 연산자를 사용하여 두 객채의 동일성을 검사합니다. 하지만 == 연산자는 객체의 실제 값을 비교 : Call By Value 하지 않고 주소값 : Call By Reference 을 비교합니다.

public class Main {
    public static void main(String[] args){
        String a = "HW";
        String b = a;
        String c = new String("HW");

        System.out.println(a==b); // true
        System.out.println(a==c); // false
        System.out.println(a.equals(c)); //true
    }
}

a와 b는 같은 주소 값을 갖고 있기 때문에 a==b는 true입니다. 하지만 c는 a와 같은 값을 갖고 있지만 새로운 객체를 생성하여 다른 주소값을 갖고 있기에 a==c는 false입니다. 마지막은 String class에서 재정의된 equals 메소드를 사용해서 실제 값을 비교한 결과로 true 가 return 됩니다.

그래서 Class 생성시 객체의 실제 값을 비교하고 싶다면 equals 메소드를 반드시 재정의 해줘야 합니다.

  • hashCode() : 객체의 유일한 Integer 값으로 Object 클래스에서는 메모리에 생성된 객체의 주소값을 변환하여 return합니다. hashCode는 HashTable과 같은 자료구조를 사용할 때 데이터가 저장되는 위치를 결정하기 위해 사용됩니다. 이 hashCode는 hashTable의 빠른 탐색에 도움을 줍니다.

equals와 hashCode의 관계

Object Class 에서는 equals(Object)가 두 객체를 같다고 판단했으면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다고 명세되어 있습니다.
그 이유는 HashMap, HashSet, Hashtable 같은 해시 기반의 컬렉션은 hashCode를 사용하기에 오류를 일으 킬 여지가 있기 때문입니다. : hashCode() 리턴 값이 우선 일치하는지 확인하고 equals() 리턴 값까지 true여야 논리적으로 같은 객체라고 판단합니다.

즉, Class에서 equals 메서드를 재정의 했다면 hashCode도 꼭 같이 재정의 해줘야 합니다.

@AllArgsConstructor
class Matrix {

    String name;
    int nums;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Matrix matrix = (Matrix) o;
        return nums == matrix.nums && Objects.equals(name, matrix.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, nums);
    }
}

public class Main {
    public static void main(String[] args){
        Matrix a = new Matrix("a", 1);
        Matrix b = new Matrix("a", 1);

        System.out.println(a.equals(b)); //true
        System.out.println(a.hashCode()); // 3969 -> hashCode값은 사람마다 다릅니다.
        System.out.println(b.hashCode()); // 3969
    }
}

하지만 주의할 점은 equls()로 비교시 false 라면 hashCode()의 값은 다를 수도, 같을 수도 있습니다. : 해시 충돌
또한 hashCode가 같다고 해서 두 객체가 반드시 같은 객체(equals()가 true)는 아닙니다.

(추가중.....)

0개의 댓글