아이템 53. 가변인수(varargs)는 신중히 사용하라.
이펙티브 자바
아이템 53. 가변인수(varargs)는 신중히 사용하라.
가변인수(varargs) 메서드는 몇시한 타입의 인수를 0개 이상 받을수 있다.
package com.github.sejoung.codetest.methods;
// 가변인수 활용 예 (320-321쪽)
public class Varargs {
// 코드 53-1 간단한 가변인수 활용 예 (320쪽)
static int sum(int... args) {
int sum = 0;
for (int arg : args)
sum += arg;
return sum;
}
public static void main(String[] args) {
System.out.println(sum());
System.out.println(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
}
실행결과
0
55
Process finished with exit code 0
위에 코드는 간단한 가변인수의 활용예 이다.
또 인수가 하나이상이어야 할수도 있다. 코드를 바꿔보면
package com.github.sejoung.codetest.methods;
// 가변인수 활용 예 (320-321쪽)
public class Varargs {
// 코드 53-2 인수가 1개 이상이어야 하는 가변인수 메서드 - 잘못 구현한 예! (320쪽)
static int min(int... args) {
if (args.length == 0)
throw new IllegalArgumentException("인수가 1개 이상 필요합니다.");
int min = args[0];
for (int i = 1; i < args.length; i++)
if (args[i] < min)
min = args[i];
return min;
}
public static void main(String[] args) {
System.out.println(min(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.println(min());
}
}
실행결과
1
Exception in thread "main" java.lang.IllegalArgumentException: 인수가 1개 이상 필요합니다.
at com.github.sejoung.codetest.methods.Varargs.min(Varargs.java:16)
at com.github.sejoung.codetest.methods.Varargs.main(Varargs.java:40)
Process finished with exit code 1
위에 코드는 문제 점이 있다. 런타임에야 코드가 실패를 한다는것이다. 그리고 코드도 장황해진다.
간결하게 바꿔보면
package com.github.sejoung.codetest.methods;
// 가변인수 활용 예 (320-321쪽)
public class Varargs {
// 코드 53-3 인수가 1개 이상이어야 할 때 가변인수를 제대로 사용하는 방법 (321쪽)
static int min(int firstArg, int... remainingArgs) {
int min = firstArg;
for (int arg : remainingArgs)
if (arg < min)
min = arg;
return min;
}
public static void main(String[] args) {
System.out.println(min(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
System.out.println(min());
}
}
컴파일 메시지
Error:(38, 28) java: method min in class com.github.sejoung.codetest.methods.Varargs cannot be applied to given types;
required: int,int[]
found: no arguments
reason: actual and formal argument lists differ in length
위에 코드는 컴파일 타임에 실패를 하고 더 코드도 명료해진다. 위에 코드의 잘 활용된 예가 System.out.printf() 이다
public PrintStream printf(String format, Object ... args) {
return format(format, args);
}
대부분의 코드가 인자 3개를 호출하고 3개이상 인자를 호출하는 경우가 극소수일때 아래와 같은 코드처럼 사용하기도 한다.
public void foo(){}
public void foo(int a1){}
public void foo(int a1, int a2){}
public void foo(int a1, int a2, int a3){}
public void foo(int a1, int a2, int a3, int... rest){}
위에 처럼 사용한 예가 EnumSet.of 메소드 이다.
public static <E extends Enum<E>> EnumSet<E> of(E e) {
EnumSet<E> result = noneOf(e.getDeclaringClass());
result.add(e);
return result;
}
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
return result;
}
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
result.add(e3);
return result;
}
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
return result;
}
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4,
E e5)
{
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
result.add(e5);
return result;
}
@SafeVarargs
public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
EnumSet<E> result = noneOf(first.getDeclaringClass());
result.add(first);
for (E e : rest)
result.add(e);
return result;
}