Effective Java/7장 메서드

Effective Java #42 varargs는 신중히 사용하라.

ktko 2018. 9. 19. 19:00


자바 가변 인자(varargs)에 대한 내용인데 포스팅 했던 내용이기에 자바 가변 인자에 대한 설명은

여기에서 보면 된다. 가변 인자에 대해 알고 있다면 계속 글을 읽으면 된다.


주어진 인자(int) 가운데 최소치를 구해야 한다고 생각할 때 이 함수는 인자 없이 호출될 수 있다고 생각하면 깔끔하게 구현되지 않는다. 실행 시점에 배열 길이를 검사해야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public final class Test {
    public static int min(int ...args) {
        if(args.length == 0)
            throw new IllegalArgumentException();
        
        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(9,2,6,7,4,7,3,1));
    }
}



위의 방법에는 몇가지 문제가 있다. 클라이언트가 인자 없이 메서드를 호출하는 것이 가능하고, 컴파일 시점이 아니라 실행 도중에 오류가 난다는 것이다. 또 한가지는 보기 흉하다. args의 유효성을 검사하는 코드를 명시적으로 넣어야 하고, min을 Integer.MAX_VALUE로 초기화 하지 않는 한 for-each문을 사용할 수도 없다.

다행히 좋은 방법은 메서드가 인자를 두 개 받도록 선언하는 것이다. 하나는 지정된 자료형을 갖는 일반 인자고, 다른 하나는 같은 자료형의 varargs 인자다. 앞에 가변 인자가 아닌 자료형의 일반 인자를 사용하게 되면 필수로 넣어야 하기 때문에 모든 문제를 해결할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
public static int min(int firstArg, int ...args) {
    if(args.length == 0)
        throw new IllegalArgumentException();
    
    int min = firstArg;
    
    for(int i=0; i < args.length; i++) {
        if(args[i] < min) min = args[i];
    }
    
    return min;
}



성능이 중요한 환경이라면 varargs 사용에 더욱 신중해야 한다. varargs 메서드를 호출할 때마다 배열이 만들어지고, 초기화가 대기 때문에 오버헤드를 감당할수 없을 거라생각된다면 다른 패턴을 따를 수도 있다. 가령 95%의 메서드를 호출할 때 3개 이하의 인자가 전달된다고 하면 아래처럼 오버로딩 메서드를 준비하는 것이다. 마지막 메서드가 인자 수가 3개보다 클 때 이용되는 varargs 메서드이다.


1
2
3
4
5
public void cal(){};
public void cal(int args1){};
public void cal(int args1, int args2){};
public void cal(int args1, int args2, int args3){};
public void cal(int args1, int args2, int args3, int ...args){};



이렇게 하면 5% 정도의 호출에 대해서만 새로운 배열이 만들어진다. 


요약하자면 varargs 메서드는 인자 개수가 가변적인 메서드를 정의할 때 편리하지만 남용되면 곤란하다. 부적절하게 사용되면 혼란스러운 결과를 초래할 수 있다.