본문 바로가기
코딩/Java

[Java] Method.invoke(...) 의 올바른 사용 방법

by KRonae 2023. 4. 2.
반응형

안녕하세요? 크로내입니다!

오늘은 Method.invoke() 를 사용하는 방법에 대해 알아보겠습니다.

 

- Static 이 아닌 메소드 실행하기

static 으로 선언되지 않은 메소드를 실행하려면 다음과 같은 코드를 사용합니다.

일단 예시로 Abc 라는 클래스를 사용하겠습니다.

// 오늘의 예시들에서 사용될 예시 클래스
public class Abc {
    private int value;
    public Abc(int i) {
        value = i;
    }
    public int get() {
        return value;
    }
    public int addAndGet(int i) {
        value += i;
        return value;
    }
    public static Abc staticMethod(int i) {
        return new Abc(i);
    }
}

일단, 저는 Abc 라는 인스턴스를 만들어서 get() 메소드를 실행하는 간단한 코드를 작성해 보겠습니다.

// 먼저 클래스를 가져와서 abcClass 변수에 저장합니다.
Class<?> abcClass = Abc.class;

// 클래스에서 int 형의 값을 받는 생성자를 가져와서 constructor 변수에 저장합니다.
Constructor<?> constructor = abcClass.getConstructor(int.class); // throws NoSuchMethodException

// static 이 아닌 메소드를 실행하기 위해 방금 가져온 생성자로, 인스턴스를 만들어 instance 변수에 저장합니다.
Object instance = constructor.newInstance(13); // throws InvocationTargetException, InstantiationException, IllegalAccessException

// abcClass 에서 get 이라는 메소드를 가져와 실행(invoke) 합니다. 이때 방금 가져온 인스턴스를 적어 static 이 아닌 메소드를 실행합니다.
// 이때 결과 값을 int 형으로 형변환 해줘야 작동합니다.
int a = (int) abcClass.getMethod("get").invoke(instance);

/* 위의 코드는 아래의 코드와 같습니다. */
// int a = new Abc(13).get();

먼저 클래스를 가져오고, 그 클래스에서 int 형을 받는 생성자를 가져옵니다.

생성자를 가져올 때, NoSuchMethodException 이 발생하는것을 참고하세요.

 

그리고 그 다음, static 이 아닌 메소드를 실행할 인스턴스를 만들어줍니다.

이때 방금 변수에 저장한 생성자를 사용합니다.

 

그리고 마지막으로, 그 인스턴스에서 get 메소드를 가져와 실행합니다.

그후 반환된 값을 int 형으로 변환하여 a 라는 int 형 변수에 저장합니다.

 

"...? 너무 쓸데가 없잖아요. 이거 method.invoke() 쓰니까 코드가 두배는 늘어났네요 ;; 이런거 누가 사용하죠? ㅡㅡ"

물론 코드가 길어지긴 했습니다. 하지만 이러한 코드는 어떠한 클래스에서 실행할지 명확하지 않을 때,

메소드의 인자로 클래스(Class<>) 값을 받아 실행할때 가끔씩 사용합니다.

그런 예시는 다음번에 다시 제대로 다뤄보겠습니다.

 

- 인자(파라미터)를 받는 메소드 실행하기

위의 코드를 잘 이해했다면, 이번것도 쉬울겁니다!

그냥 abcClass.getMethod(...).invoke(instance) 부분을 아주 조금만 건들면 되니까요.

바로 예시코드 부터 보겠습니다.

Class<?> abcClass = Abc.class;

Constructor<?> constructor = abcClass.getConstructor(int.class); // throws NoSuchMethodException
Object instance = constructor.newInstance(13); // throws InvocationTargetException, InstantiationException, IllegalAccessException

// 마찬가지로 abcClass 에서 addAndGet 메소드를 가져와 실행합니다. 이번엔 getMethod(이름, 인자 클래스...) 에서 앞쪽 메소드 이름 다음에 넣어야 할 인자의 값의 형식을 설정합니다.
// 그 다음 그 메소드를 invoke(인스턴스, 인자...) 로 실행합니다. 인자는 여러번 적을 수 있음을 알려드립니다.
int b = (int) abcClass.getMethod("addAndGet", int.class).invoke(instance, 12);

/* 위의 코드는 아래의 코드와 같습니다. */
// int b = new Abc(13).addAndGet(12);

이번에는 invoke 부분과 getMethod 부분에 전달하는 인자가 하나 더 늘었습니다.

getMethod를 보면, 

public Method getMethod(String name, Class<?>... parameterTypes);

이렇게 선언되어있습니다. parameterTypes 를 여러개 받을 수 있게 되어있는데요,

원하는 인자(파라미터) 를 클래스로 여러개 적을 수 있게 되어있는 것 같습니다.

그러니까, getMethod(이름, 클래스, 클래스, 클래스···) 이런 식으로 클래스를 여러개 적을 수 있다는거죠.

(참고로 이 클래스에는 invoke 부분에서 보낼 값들의 클래스를 적으면 됩니다)

 

- Static 메소드 실행하기

위의 코드들이 모두 잘 이해되었나요? 좋습니다!

그럼 이제 static 메소드를 실행할 차례입니다.

다음 예시 코드를 살펴볼까요?

Class<?> abcClass = Abc.class;

Constructor<?> constructor = abcClass.getConstructor(int.class); // throws NoSuchMethodException
Object instance = constructor.newInstance(13); // throws InvocationTargetException, InstantiationException, IllegalAccessException

// 메소드 staticMethod 를 가져와 실행합니다. 이때 instance 를 적던 부분을 null 로 설정하여, static 메소드를 실행합니다.
int c = ((Abc) abcClass.getMethod("staticMethod", int.class).invoke(null, 31)).get();

/* 위의 코드는 아래의 코드와 같습니다. */
// int c = Abc.staticMethod(31).get();

위의 코드는,  전에 instance 를 넣던 부분을 null 로 설정하여, static 메소드를 실행했습니다!

 

저는 이걸 찾느라 정말 오래 걸렸는데, 이렇게 보니 정말 쉬운 것, 바로 Method.invoke(instance, parm...) 이였습니다.

끝까지 읽어주셔서 감사합니다.

 

질문이 있으시다면 댓글이나, msg.kronae@gmail.com 으로 연락 바랍니다!

그럼 이만, 지금까지 크로내였습니다! 감사합니다~

반응형

'코딩 > Java' 카테고리의 다른 글

[Java] Timer 클래스를 이용해 Interval 만들기!  (0) 2023.03.09

댓글