Java

Object 의 toString 부터 hashCode 까지

be-student 2023. 2. 19. 11:03

이 글을 쓰게 된 이유

Object 클래스에 대해서 생각보다 모르는 것들이 많았고, 이번 기회에 자세하게 알아보아야 겠다는 생각이 들었는데요

알아보는 김에 우아한테크코스 프리코스때 리뷰가 나왔던 부분 먼저 자세하게 알아보면서 진행해보려고 합니다

toString 메서드 알아보기

이 부분이 실제 toString 메서드에 대한 정의인데요

 

리턴하는 값은 오브젝트를 나타내는 스트링이라고 적혀 있습니다

toString 메서드는 오브젝트를 텍스트로 나타내는 텍스트를 나타내고, 사람이 읽기 좋은 좋은 결과를 반환해야 한다고 정의되어있습니다

모든 오브젝트를 상속하는 클래스(사실상 모든 클래스) 가 이 메서드를 오버라이딩 하는 것을 권장하고 있다고 합니다

 

계속 안정적일 필요도 없고, JVM  호출에서 안정적으로 유지될 필요도 없다고 하는 메시지이기 때문에, 이 부분을 생각했을 때, 실제로 로직에 사용하라는 메서드가 아니라 사람이 읽기 위한 용도라는 것은 명확해보입니다

 

 getClass().getName() + '@' + Integer.toHexString(hashCode())

여기서 @은 unsigned hexadecimal 이라는 의미를 가지고 있습니다

 

hashCode 메서드 알아보기

toString 메서드에서 호출되는 hashCode 메서드를 알아보도록 하겠습니다

먼저 처음보는 어노테이션부터 알아보려고 합니다

 

@IntrinsicCandidate

 

이 어노테이션이 붙은 메서드는 HotSpot JVM 에게 아마도 hot 하게 호출될 것 같으니 네이티브 코드로 바꿔두어라 라는 내용을 담고 있습니다

대부분의 경우에 자바 코드 자체이거나, 라이브러리 코드에 있기 때문에, 실제로 사용하는 경우는 없다고 생각하셔도 될 것 같네요

 

바이트코드가 암시적으로 계속해서 NullPointerException 이나, ArrayStoreException 같은 것들을 계속해서 체킹해주기에, 안정적인 경우가 많았는데요

이 어노테이션을 달아버리면, 이런 부분이 스킵되고, 바로 Native 코드로 컴파일될 가능성이 높아집니다

따라서 안정성을 보장하기 위해서 NullPointerException, ArrayOutboundException , 0/0 같은 체크를 해줘야 합니다

 

이것을 작성하더라도, 당연하지만 무조건 네이티브 코드가 된다는 보장이 없기도 합니다 

라이브러리 관리자나, 직접 JVM을 만드는 입장이 아니라면 무시해도 괜찮을 것 같습니다

 

자바 어노테이션에 대해 알아보기

항상 어노테이션을 보게 되면 

꼭 달려있는 내용들이 있는데요

1. Documented

2. Retention

3. Target

이렇게 3가지가 달려있습니다

 

Documented

한줄 요약

이 어노테이션이 있다면, javadoc 같은 문서 도구들이 내용을 출력해준다

 

구체적으로는 

@Documented 어노테이션이 달려있는 어노테이션A가 있고

@Documented 가 없는 어노테이션 B가 있고

달려있는 Element가 있을 떄

Element 가 A에 달려있는 여러 조건들을 만족한다는 것을 의미합니다

B를 사용했을 떄는 어떤 식으로 구현되는지를 알려주지 않아도 된다는 것을 의미합니다

 

Target

어디에 이 어노테이션을 사용할 수 있는지가 적혀있습니다

컴파일러가 이를 확인하고, 어디에 적용할 수 있는지에 대해서 체크하고, 알려주기위한 내용이 가장 큽니다

public enum ElementType {
    /** Class, interface (including annotation interface), enum, or record
     * declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation interface declaration (Formerly known as an annotation type.) */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE,

    /**
     * Module declaration.
     *
     * @since 9
     */
    MODULE,

    /**
     * Record component
     *
     * @jls 8.10.3 Record Members
     * @jls 9.7.4 Where Annotations May Appear
     *
     * @since 16
     */
    RECORD_COMPONENT;
}

 

이런 곳에다가 사용할 수 있다고 하네요

Retention 알아보기

이 어노테이션이 어디까지 지속되어야 하는지를 알려주는 어노테이션입니다

기본으로 CLASS 파일까지는 기록되는 방식입니다

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

컴파일시에 바로 버려지는 Source

CLASS 파일까지 기록되는 CLASS

실행시까지 작용해야하는 RUNTIME 이렇게 3가지가 있습니다

 

hashCode 알아보기

동등하다면 같은 값을 반환해야 합니다

당연하지만 달라도 같은 값을 반환해도 됩니다 모두 같은 값이라도 문제는 없지만 성능상 문제가 있을 수 있다는 의미이기도 합니다

 This integer need not remain consistent from one execution of an application to another execution of the same application.

이 부분에 대해서는 아직 잘 모르겠네요