본문 바로가기
Everyday Study

2024.08.21(수) { enum 클래스의 자동생성되는 것, InvocationHandler }

by xogns93 2024. 8. 21.

enum 클래스의 자동생성되는 것들

 

1. values() 메서드

  • 자동 생성: values() 메서드는 모든 enum 클래스에서 자동으로 생성됩니다. 이 메서드는 enum의 모든 상수를 배열로 반환합니다.
  • 사용 예:
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

public class Main {
    public static void main(String[] args) {
        // values() 메서드를 사용하여 enum의 모든 상수를 가져옵니다.
        Day[] days = Day.values();
        for (Day day : days) {
            System.out.println(day);
        }
    }
}
  • 출력:
    MONDAY
    TUESDAY
    WEDNESDAY
    THURSDAY
    FRIDAY
    SATURDAY
    SUNDAY

 

2. valueOf(String name) 메서드

  • 자동 생성: valueOf(String name) 메서드도 자동으로 생성됩니다. 이 메서드는 enum의 이름을 기반으로 특정 enum 상수를 반환합니다.
  • 사용 예:
Day day = Day.valueOf("MONDAY");
System.out.println(day); // MONDAY

 

3. 생성자

  • 자동 생성: enum 클래스는 일반 클래스와 달리 생성자가 자동으로 제공됩니다. enum 생성자는 암묵적으로 private이며, 외부에서 인스턴스를 생성할 수 없습니다.
  • 사용 예:
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    private Day() {
        System.out.println(this + " 생성자 호출");
    }
}

public class Main {
    public static void main(String[] args) {
        Day day = Day.MONDAY; // 여기서 생성자가 호출됩니다.
    }
}
  • 출력:
    MONDAY 생성자 호출
    TUESDAY 생성자 호출
    WEDNESDAY 생성자 호출
    THURSDAY 생성자 호출
    FRIDAY 생성자 호출
    SATURDAY 생성자 호출
    SUNDAY 생성자 호출

 

Java에서 enum은 클래스로 정의되며, 각 enum 상수는 해당 enum 클래스의 인스턴스입니다. enum 클래스가 로드될 때, JVM은 해당 클래스의 모든 상수를 미리 생성합니다. 즉, enum 클래스가 처음 사용될 때 (예: Day.MONDAY를 참조할 때), JVM은 enum의 모든 상수들을 인스턴스화합니다.

이 때문에 Day.MONDAY를 참조할 때 Day 클래스의 모든 상수(MONDAY, TUESDAY, WEDNESDAY, etc.)에 대한 생성자가 호출됩니다. 그래서 Day.MONDAY를 한 번 참조했지만, 다른 상수들에 대한 생성자도 모두 호출된 것입니다.

 

 

4. ordinal() 메서드

  • 자동 생성: ordinal() 메서드는 해당 enum 상수의 순서를 반환합니다. 첫 번째 상수의 순서는 0입니다.
  • 사용 예:
int index = Day.MONDAY.ordinal();
System.out.println(index); // 0

요약

  • 자동 생성되는 메서드:
    • values(): 모든 enum 상수를 배열로 반환합니다.
    • valueOf(String name): 이름으로 enum 상수를 반환합니다.
    • ordinal(): enum 상수의 순서를 반환합니다.
  • 자동 생성되는 생성자:
    • enum 생성자는 자동으로 제공되며 private입니다. 외부에서 인스턴스를 생성할 수 없습니다.

이처럼 enum 클래스에는 자동으로 제공되는 메서드와 생성자가 있어서 별도로 구현하지 않아도 기본적인 기능을 사용할 수 있습니다.

 

 


InvocationHandler

 

InvocationHandler는 자바의 리플렉션 API에서 동적 프록시(Dynamic Proxy)를 구현할 때 사용되는 인터페이스입니다InvocationHandler를 사용하면 메서드 호출을 가로채고, 해당 메서드가 어떻게 동작할지 동적으로 결정할 수 있습니다. 동적 프록시는 런타임에 생성되며, 인터페이스를 구현하는 클래스를 대신하여 동작할 수 있습니다.

 

CalculatorService 인터페이스 정의

// 간단한 계산기 서비스 인터페이스
public interface CalculatorService {
    int add(int a, int b);
    int subtract(int a, int b);
}

 

CalculatorServiceImpl 클래스 정의 ( CalculatorService 인터페이스 구현 )

// CalculatorService 인터페이스를 구현한 실제 서비스 클래스
public class CalculatorServiceImpl implements CalculatorService {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int subtract(int a, int b) {
        return a - b;
    }
}

 

InvocationHandler 구현

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// InvocationHandler 구현체, 여기서 CalculatorService의 메서드 호출을 가로챕니다.
public class CalculatorInvocationHandler implements InvocationHandler {

    private CalculatorService target; // 실제 메서드를 호출할 CalculatorService 객체

    public CalculatorInvocationHandler(CalculatorService target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 메서드 호출 전에 로그를 남깁니다.
        System.out.println("메서드 " + method.getName() + " 호출 중입니다. 매개변수: " + args[0] + ", " + args[1]);

        // 실제 객체의 메서드를 호출합니다.
        Object result = method.invoke(target, args);

        // 메서드 호출 후 결과를 로그에 남깁니다.
        System.out.println("메서드 " + method.getName() + " 호출이 끝났습니다. 결과: " + result);

        return result;
    }
}

 

프록시 생성 및 사용

import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        // 실제 서비스 객체 생성
        CalculatorService calculatorService = new CalculatorServiceImpl();

        // InvocationHandler 구현체를 통해 프록시 생성
        CalculatorService proxyInstance = (CalculatorService) Proxy.newProxyInstance(
            calculatorService.getClass().getClassLoader(),
            calculatorService.getClass().getInterfaces(),
            new CalculatorInvocationHandler(calculatorService)
        );

        // 프록시 객체를 통해 메서드를 호출
        int addResult = proxyInstance.add(5, 3);
        int subtractResult = proxyInstance.subtract(10, 7);
    }
}
메서드 add 호출 중입니다. 매개변수: 5, 3
메서드 add 호출이 끝났습니다. 결과: 8
메서드 subtract 호출 중입니다. 매개변수: 10, 7
메서드 subtract 호출이 끝났습니다. 결과: 3