[Reflection] Varargs 에 Array type 을 전달하는 방법

Lofri·2024년 2월 22일

1. 개요

Spring AOP 중 method args(Object[] type) 를 받아 특정 method 를 앞에서 받은 args로 invoke 하는 로직을 작성하던 중 Method.invoke(targetObject, Object[]) 호출이 의도하는 대로 동작하지 않는 현상을 발견했다.

그 이유는 Method.invoke(Object, Object... args) 가 Object[] type 의 parameter 를 varargs 로 인식해 받아서 였기 때문인데, 이를 기록하고 java varargs 에 대해 살짝 짚어보고자 한다.
이슈였던 상황


2. Varargs

개발을 하면서 이런 상황을 맞이할 수 있다. 생성한 메소드가 얼마나 많은 argument 를 받을 지 모르겠는 상황. 그것을 해결하기 위해 varargs 가 생겨났다.

Java 1.5 에 처음 소개된 VarargsVariable arguments 의 약어로서 이름 그대로 임의의 개수의 메소드 argument 를 받을 수 있게 해주는 기능이다.

메소드 인자를 array 로 만들어 주는 단축방법이다.

3. 규칙

Varargs 사용에는 두가지 원칙이 있다.

  1. Varargs parameter 는 하나만 가질 수 있다.
  2. Varargs parameter 는 마지막이어야 한다.

위 규칙에 따라 자바 컴파일러는 주어진 Varargs 를 메소드가 사용될 때 마다
주어진 파라미터를 가질 array 를 생성하여 변수로 넘겨준다.

예시

1번 조건에 의해

void foo1(String... v1) {
	// 1번 조건 만족
}
void foo2(int... v1, String... v2) { 
	// Compile time error
}

foo1 은 가능하나, foo2 는 가능하지 않다.

2번 조건에 의해

void foo1(int v1, String... v2) {
	// 2번 조건 만족
}
void foo2(String... v1, int v1) {
	// Compile time error
}

foo1 은 가능하나, foo2 는 가능하지 않다.


4. 그래서 왜 발생했을까

java Vararg 는 array type 의 input 이 들어올 경우 이를 varargs 의 인자값으로 생각한다.

예를들어 아래 메소드가 있다고 생각해보자.

public void foo(Object[] args);

이를 reflect 하고 invoke 를 할 때 만약 인자값으로 Object[] 를 넣는다면

Method method = TestClass.class.getDeclaredMethod("foo", String[].class);
Object[] args = {"1", "2"}
method.invoke(instance, args);

오류가 발생한다.

이는 컴파일러가 인풋으로 들어온 Object[] 를 하나의 argument 로 본게 아니라 arguments 로 봤기 때문이다.

따라 입력 값을 아래와 같이

method.invoke(instance, new Object[] {args});
// or
method.invoke(instance, (Object) args);

캐스팅해준다면 원하는 결과를 얻을 수 있다.


99. References

[Baeldung] Varargs in Java
[Programiz] Java Varargs
[[Coderanch] Passing an array into a vararg method (in Reflection API)]

profile
Java BE

0개의 댓글