Java에서 Class 객체의 활용 방법

Java는 객체 지향 프로그래밍 언어로서 모든 것은 객체로 표현됩니다. 이러한 객체를 구현하기 위해 필요한 핵심 개념 중 하나가 Class입니다. 실제로 클래스 자체도 객체이며, java.lang.Class의 인스턴스로 존재합니다.

클래스가 객체라는 점을 이해하려면 다음 예제를 살펴보세요:

package com.edu.hpu;

public class Example {
    public static void main(String[] args) {
        // 1. 인스턴스 생성 후 getClass()로 Class 객체 얻기
        Foo instance = new Foo();
        Class<?> clazz1 = instance.getClass();

        // 2. 클래스 리터럴 사용 (정적 참조)
        Class<?> clazz2 = Foo.class;

        // 3. 클래스 이름으로 동적으로 로드 (동적 로딩)
        Class<?> clazz3 = null;
        try {
            clazz3 = Class.forName("com.edu.hpu.Foo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 세 가지 방식 모두 동일한 클래스 정보를 반환
        System.out.println(clazz1 == clazz2); // true
        System.out.println(clazz1 == clazz3); // true

        // Class 객체를 이용해 인스턴스 생성
        try {
            Foo newInstance = (Foo) clazz1.newInstance();
            newInstance.execute();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class Foo {
    public void execute() {
        System.out.println("Foo 실행 중...");
    }
}

위 코드에서 보듯이 Class 객체는 클래스의 메타정보를 담고 있으며, 이는 런타임에 클래스를 동적으로 생성하거나 조작할 수 있게 해줍니다. 세 가지 방법 모두 같은 메타정보를 공유하므로, 비교 연산 결과는 항상 true입니다.

다음은 실용적인 사례입니다. 기존 코드에서는 특정 클래스를 미리 정의하고 컴파일 시점에 의존하지만, 이를 동적 로딩으로 변경하면 확장성이 훨씬 좋아집니다.

public class DynamicLoader {
    public static void main(String[] args) {
        try {
            // 입력된 클래스 이름을 기반으로 동적으로 로드
            Class<?> loadedClass = Class.forName(args[0]);
            
            // 인터페이스 타입으로 캐스팅하여 메서드 호출
            OfficeTool tool = (OfficeTool) loadedClass.newInstance();
            tool.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
interface OfficeTool {
    void run();
}
class WordTool implements OfficeTool {
    @Override
    public void run() {
        System.out.println("Word 문서 작성 시작...");
    }
}
class ExcelTool implements OfficeTool {
    @Override
    public void run() {
        System.out.println("Excel 시트 처리 중...");
    }
}

이 방식을 통해 프로그램 실행 시점에 어떤 클래스를 사용할지 결정할 수 있으며, 새로운 도구 클래스를 추가해도 기존 코드 수정 없이 확장 가능합니다. 이는 플러그인 기반 아키텍처나 모듈화된 시스템 설계에 매우 유용합니다.

태그: java Class reflection dynamic loading Interface

5월 25일 09:19에 게시됨