Spring AOP 중 method args(Object[] type) 를 받아 특정 method 를 앞에서 받은 args로 invoke 하는 로직을 작성하던 중 Method.invoke(targetObject, Object[]) 호출이 의도하는 대로 동작하지 않는 현상을 발견했다.
그 이유는 Method.invoke(Object, Object... args) 가 Object[] type 의 parameter 를 varargs 로 인식해 받아서 였기 때문인데, 이를 기록하고 java varargs 에 대해 살짝 짚어보고자 한다.
이슈였던 상황
개발을 하면서 이런 상황을 맞이할 수 있다. 생성한 메소드가 얼마나 많은 argument 를 받을 지 모르겠는 상황. 그것을 해결하기 위해 varargs 가 생겨났다.
Java 1.5 에 처음 소개된 Varargs 는 Variable arguments 의 약어로서 이름 그대로 임의의 개수의 메소드 argument 를 받을 수 있게 해주는 기능이다.
메소드 인자를 array 로 만들어 주는 단축방법이다.
Varargs 사용에는 두가지 원칙이 있다.
위 규칙에 따라 자바 컴파일러는 주어진 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 는 가능하지 않다.
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);
캐스팅해준다면 원하는 결과를 얻을 수 있다.
[Baeldung] Varargs in Java
[Programiz] Java Varargs
[[Coderanch] Passing an array into a vararg method (in Reflection API)]