Object 클래스의 메서드

Object 클래스는 java.lang 패키지의 클래스 계층 구조 트리의 맨 위에 있습니다. 모든 클래스는 Object 클래스의 직간접적인 자손입니다. 사용하거나 작성하는 모든 클래스는 Object의 인스턴스 메서드를 상속합니다. 이러한 메서드를 사용할 필요는 없지만, 사용하려는 경우 클래스 고유의 코드로 재정의해야 할 수도 있습니다. 이 섹션에서 설명하는 Object에서 상속된 메서드는 다음과 같습니다:

Java SE 9부터 finalize() 메서드가 더 이상 사용되지 않는다는 점에 유의하세요. 이 메서드를 재정의하는 것은 강력히 권장하지 않습니다.

Objectnotify(), notifyAll(), wait() 메서드는 모두 프로그램에서 독립적으로 실행되는 스레드의 활동을 동기화하는 역할을 하는데, 이는 이후 섹션에서 설명하므로 여기서는 다루지 않겠습니다. 이러한 메서드에는 다섯 가지가 있습니다:

Note: 이러한 방법에는 몇 가지 미묘한 측면이 있으며, 특히 복제 방법은 더욱 그렇습니다.

 

The toString() Method

클래스에서 항상 toString() 메서드를 재정의하는 것을 고려해야 합니다.

객체의 toString() 메서드는 디버깅에 매우 유용한 객체의 String 표현을 반환합니다. 객체에 대한 String 표현은 전적으로 객체에 따라 달라지므로 클래스에서 toString()을 재정의해야 합니다.

Book의 인스턴스와 같은 객체의 텍스트 표현을 표시하려면 toString()System.out.println()과 함께 사용할 수 있습니다:

System.out.println(firstBook.toString());

적절하게 재정의된 toString() 메서드의 경우 다음과 같이 유용한 내용을 출력합니다:

ISBN: 0201914670; The Swing Tutorial; A Guide to Constructing GUIs, 2nd Edition

 

The equals() Method

equals() 메서드는 두 개체가 동일한지 비교하여 같으면 참을 반환합니다. Object 클래스에서 제공하는 equals() 메서드는 동일성 연산자(==)를 사용하여 두 객체가 동일한지 여부를 결정합니다. 원시 데이터 타입의 경우 올바른 결과를 제공합니다. 그러나 객체의 경우 그렇지 않습니다. Object에서 제공하는 equals() 메서드는 객체 참조가 동일한지, 즉 비교 대상이 정확히 동일한 객체인지 여부를 테스트합니다.

두 객체가 동등성(동일한 정보를 포함하는)의 의미에서 동일한지 테스트하려면 equals() 메서드를 재정의해야 합니다. 다음은 equals()를 재정의하는 Book 클래스의 예입니다:

public class Book {
    String ISBN;
    
    public String getISBN() { 
        return ISBN;
    }
    
    public boolean equals(Object obj) {
        if (obj instanceof Book)
            return ISBN.equals((Book)obj.getISBN()); 
        else
            return false;
    }
}

Book 클래스의 두 인스턴스가 동일한지 테스트하는 다음 코드를 살펴봅시다:

// Swing Tutorial, 2nd edition
Book firstBook  = new Book("0201914670");
Book secondBook = new Book("0201914670");
if (firstBook.equals(secondBook)) {
    System.out.println("objects are equal");
} else {
    System.out.println("objects are not equal");
}

이 프로그램은 첫 번째 책두 번째 책이 서로 다른 두 개체를 참조하더라도 개체가 동일하다고 표시합니다. 비교되는 객체에 동일한 ISBN 번호가 포함되어 있기 때문에 동일한 것으로 간주됩니다.

동일성 연산자가 클래스에 적합하지 않은 경우 항상 equals() 메서드를 재정의해야 합니다.

Note: equals()를 재정의하는 경우, hashCode()도 재정의해야 합니다.

 

The hashCode() Method

hashCode()가 반환하는 값은 해싱 알고리즘에 의해 생성된 정수 값인 객체의 해시 코드입니다.

정의에 따라 두 객체가 같으면 해시 코드도 같아야 합니다. equals() 메서드를 재정의하면 두 객체가 동일해지는 방식이 변경되고 ObjecthashCode()의 구현이 더 이상 유효하지 않습니다. 따라서 equals() 메서드를 재정의하는 경우 hashCode() 메서드도 함께 재정의해야 합니다.

 

The getClass() Method

getClass()를 재정의할 수 없습니다.

getClass() 메서드는 이름(getSimpleName(), 슈퍼클래스(getSuperclass() 및 구현된 인터페이스(getInterfaces() 등 클래스에 대한 정보를 가져오는 데 사용할 수 있는 메서드가 있는 Class 객체를 반환합니다. 예를 들어, 다음 메서드는 객체의 클래스 이름을 가져와 표시합니다:

void printClassName(Object obj) {
    System.out.println("The object's" + " class is " +
        obj.getClass().getSimpleName());
}

java.lang 패키지의 Class 클래스에는 많은 수의 메서드(50개 이상)가 있습니다. 예를 들어 클래스가 주석(isAnnotation()), 인터페이스(isInterface()) 또는 열거형(isEnum())인지 여부를 테스트할 수 있습니다. 객체의 필드가 무엇인지(getFields()) 또는 메서드가 무엇인지(getMethods()) 등을 확인할 수 있습니다.

 

The clone() Method

클래스 또는 그 슈퍼클래스 중 하나가 Cloneable 인터페이스를 구현하는 경우, clone() 메서드를 사용하여 기존 객체에서 복사본을 생성할 수 있습니다. 복제본을 만들려면 다음과 같이 작성합니다:

aCloneableObject.clone();

Object의 이 메서드 구현은 clone()가 호출된 객체가 Cloneable 인터페이스를 구현하는지 여부를 확인합니다. 그렇지 않은 경우, 메서드는 CloneNotSupportedException 예외를 던집니다. 예외 처리는 예외 섹션에서 다룹니다. 현재로서는 clone()을 다음과 같이 선언해야 한다는 것을 알아야 합니다.

protected Object clone() throws CloneNotSupportedException

or

public Object clone() throws CloneNotSupportedException

clone() 메서드를 작성하여 Object에 있는 메서드를 재정의하려는 경우.

clone()이 호출된 객체가 Cloneable 인터페이스를 구현하는 경우, Object의 clone() 메서드는 원래 객체와 같은 클래스의 객체를 생성하고 새 객체의 멤버 변수가 원래 객체의 해당 멤버 변수와 동일한 값을 갖도록 초기화합니다.

클래스를 복제 가능하게 만드는 가장 간단한 방법은 클래스의 선언에 implements Cloneable을 추가하는 것입니다. 그러면 객체는 clone() 메서드를 호출할 수 있습니다.

일부 클래스의 경우 객체의 clone() 메서드의 기본 동작이 정상적으로 작동합니다. 그러나 객체에 외부 객체에 대한 참조가 포함된 경우(예: ObjExternal), 올바른 동작을 얻으려면 clone()를 재정의해야 할 수 있습니다. 그렇지 않으면 한 객체가 변경한 ObjExternal의 변경 사항이 복제본에도 표시됩니다. 즉, 원본 오브젝트와 그 클론이 독립적이지 않으므로 이를 분리하려면 clone()을 재정의하여 오브젝트와 ObjExternal을 복제하도록 해야 합니다. 그러면 원본 객체는 ObjExternal을 참조하고 클론은 ObjExternal의 클론을 참조하므로 객체와 클론이 실제로 독립적입니다.

 

The finalize() Method

Object 클래스는 객체가 가비지가 될 때 호출할 수 있는 콜백 메서드인 finalize()를 제공합니다. 객체의 finalize() 구현은 아무 일도 하지 않습니다. 리소스 해제와 같은 정리를 위해 finalize()를 재정의할 수 있습니다.

finalize() 메서드는 시스템에 의해 자동으로 호출될 수 있지만, 언제 호출되는지 또는 호출되더라도 불확실합니다. 따라서 이 메서드에 의존하여 정리를 수행해서는 안 됩니다. 예를 들어, I/O를 수행한 후 코드에서 파일 디스크립터를 닫지 않고 finalize()가 대신 닫아줄 것으로 기대하면 파일 디스크립터가 부족할 수 있습니다.

Java SE 9부터 finalize() 메서드는 더 이상 사용되지 않습니다. 이제 이 메서드를 재정의하는 것은 강력히 권장하지 않습니다. 일부 리소스를 정리해야 하는 경우 AutoCloseable 인터페이스를 구현하여 정리할 수 있습니다. 이 점은 Java IO API 섹션에서 자세히 다루고 있습니다.