프로그래밍/Java

[Java] JDK 부수기 - (3) java.lang.Class

Churnobyl 2023. 12. 4. 16:20
728x90
반응형

 


java.lang.Class

Instances of the class Class represent classes and interfaces in a running Java application. An enum class and a record class are kinds of class; an annotation interface is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects
'Class' 클래스의 각각의 인스턴스들은 실행중인 자바 애플리케이션의 클래스들과 인터페이스들을 대표한다. enum 클래스와 record 클래스는 클래스의 일종이며, annotation 인터페이스는 인터페이스의 일종이다. 요소의 타입과 차원의 수가 같은 모든 배열은 모두 동일한 'Class' 객체에 속한다. boolean, byte, char, shor, int, long, float, double과 같은 원시 타입과 void 키워드 또한 'Class' 객체로  대표된다.

 

 'Class' 클래스는 위의 설명대로 각 클래스를 대표하며 'Class'객체는 각 클래스마다 하나씩 가진다. 이게 무슨 뜻이냐면 A라는 임의의 클래스의 인스턴스 a, b, c, d, e, ...가 있다면 모두 클래스 A를 대표하는 A라는 같은 'Class'객체를 가지고 있다는 뜻이다. 이 'Class' 클래스는 각 클래스에 관련된 메타데이터를 담고 있다. 예를 들어 A라는 임의의 클래스가 있다면 A라는 클래스의 이름(getName() 메서드), A의 상위 클래스 정보(getSuperClass() 메서드), A가 가진 메서드 정보(getMethods() 메서드), A를 로드한 클래스 로더 정보(getClassLoader() 메서드), A가 속한 패키지 정보(getPackage() 메서드) 등등의 정보들을 얻을 수 있다. 따라서 어떤 객체의 클래스에 대한 정보를 얻고 싶다면 해당 객체의 'Class' 객체로부터 정보를 찾을 수 있는 것이다.

 

 각 클래스의 'Class' 객체는 자바 애플리케이션이 실행될 때 JVM에 의해서 자동적으로 생성된다. 이 부분은 다음 글의 주인공인 ClassLoader 클래스에서 더 자세히 설명하겠지만 간단히 설명하면, JVM이 실행될 때 세 가지 계층으로 구분된 ClassLoader에 의해 필요한 .class파일들을 메모리에 올리고 링킹하고 초기화한 뒤 최종적으로 'Class'객체를 생성하는 과정을 거친다. 따라서 'Class'객체를 개발자가 직접 조작할 일은 없고 필요에 따라 잘 사용하면 된다.

 

 결론적으로 'Class' 객체는 ClassLoader에 의한 산물 같은 느낌으로 'Class' 객체 자체가 뭘 수행한다기보다 클래스에 대한 다양한 정보를 캡슐화한 정보 객체라고 할 수 있다. 그러므로 이번 글에서는 'Class' 클래스가 제공하는 수많은 메서드 사용 결과 중 일부를 간단히 알아보기만 하면 될 것 같다.

 


메서드 (Methods)

 

많아서 docs 링크로 대체. 여기

 

 

 'Class' 클래스의 메서드는 큼지막하게 분류하더라도 조회, 생성, 검사, 캐스팅 등 다양한 메서드를 가지고 있다. 그 중에서 클래스 관련 정보를 조회하는 기능만 간단하게 살펴보고 이 글은 마무리 짓도록 하자.


클래스 정보 조회

대부분 get으로 시작하며 클래스 자체에 관련한 정보를 조회하는 메서드

 

package domain;

public interface Animal {

    public void move();
    public void eat();
    public void sleep();
    
}
package domain;

public class Primate implements Animal {

    String name;

    public Primate() {
        this.name = name;
    }

    @Override
    public void move() {
        System.out.printf("%s는 걷습니다.", name);
    }

    @Override
    public void eat() {
        System.out.printf("%s는 먹습니다.", name);
    }

    @Override
    public void sleep() {
        System.out.printf("%s는 잡니다.", name);
    }
}
package domain;

public interface Mortal {
    public void die();
}
package domain;

import jdk.jfr.Description;

@Description("a Person")
public class Person extends Primate implements Mortal {

    public int head = 1;
    public int body = 1;
    public int legs = 2;

    String name;

    public Person(String name) {
        super();
    }

    public void throwing() {
        System.out.printf("%s가 던집니다.", name);
    }

    @Override
    public void die() {
        System.out.printf("%s는 죽습니다.", name);
    }
}
import domain.Person;

import java.util.Arrays;

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

        // getName() : 해당 클래스 객체가 대표하는 이름 리턴 (String)
        System.out.println(Person.class.getName());
        System.out.println("================================");
        // getSuperClass() : 해당 클래스 객체의 상위 'Class' 객체를 리턴 (Class)
        System.out.println(Person.class.getSuperclass());
        System.out.println("================================");
        // getInterfaces() : 해당 클래스 객체가 implements하는 인터페이스의 'Class' 객체들 리턴 (Class[])
        System.out.println(Arrays.toString(Person.class.getInterfaces()));
        System.out.println("================================");
        // getFields() : 해당 클래스에서 접근할 수 있는(public) 필드 객체들 리턴 (Field[])
        System.out.println(Arrays.toString(Person.class.getFields()));
        System.out.println("================================");
        // getMethods() : 해당 클래스에서 접근할 수 있는(public) 메서드 객체들 리턴 (Method[])
        System.out.println(Arrays.toString(Person.class.getMethods()));
        System.out.println("================================");
        // getAnnotations() : 해당 클래스에 붙어있는 Annotation들을 리턴 (Annotation[])
        System.out.println(Arrays.toString(Person.class.getAnnotations()));
    }
}
domain.Person
================================
class domain.Primate
================================
[interface domain.Mortal]
================================
[public int domain.Person.head, public int domain.Person.body, public int domain.Person.legs]
================================
[public void domain.Person.die(), public void domain.Person.throwing(), public void domain.Primate.eat(), public void domain.Primate.sleep(), public void domain.Primate.move(), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
================================
[@jdk.jfr.Description("a Person")]

 

반응형