JAVA/Effective Java

[아이템 53] 가변인수는 신중히 사용하라

꾸준함. 2024. 3. 11. 01:59

가변인수

자바 5+ 버전부터 등장한 가변인수 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있습니다.

가변인수 메서드를 호출하면 다음과 같이 처리합니다.

  • 가장 먼저 인수의 개수와 길이가 같은 배열을 생성하고
  • 인수들을 해당 배열에 저장하여 가변인수 메서드에 건네줌

 

다음 코드는 입력받은 int 인수들의 합을 계산하는 예제입니다.

 

 

위 코드에서 볼 수 있다시피 가변인수 적용 시 메서드를 보다 간결하고 유연하게 만들어주므로, 적절하게 사용하면 코드의 가독성과 유지보수성을 향상할 수 있습니다.

 

여기까지만 봐서는 가변인수를 무조건 적용해야 하는 것처럼 보이지만, 가변인수 사용 시 몇 가지 규칙과 주의사항이 있습니다.

  • 인수를 0개만 받도록 설계하는 것은 좋지 않음
  • 힙 오염 주의
  • 성능 이슈
  • 메서드 당 한 개의 가변인수만 사용 가능

 

1. 인수를 0개만 받도록 설계하는 것은 좋지 않음

 

인수 개수는 런타임에 가변인수에 의해 자동으로 생성된 배열의 길이로 알 수 있습니다.

따라서 최솟값을 구하는 메서드처럼 인수를 0개만 넣었을 때 런타임 에러가 발생하는 코드를 컴파일 시점에 잡아낼 수 없습니다.


 

 

다행히도 해당 문제에 대한 해결책이 존재합니다.

다음 코드처럼 첫 번째로는 평범한 매개변수를 받고, 가변인수는 두 번째로 받으면 앞서의 문제가 말끔히 사라집니다.


 

2. 힙 오염 주의

 

아이템 32에서 언급했다시피 제네릭과 함께 가변인수 사용 시 힙 오염이 발생할 수 있습니다.

  • 힙 오염은 제네릭으로 타입이 정의된 데이터 구조에서 실제로는 다른 타입의 데이터가 저장되는 상황
  • 일반적으로 제네릭은 컴파일 시에 타입 안전성을 보장하기 위해 사용
  • 그러나 가변인자(varargs)나 배열과 같은 특정 상황에서 제네릭이 제대로 동작하지 않으면 힙 오염이 발생 가능


 

코드 부연 설명

  • dangerous 메서드는 List<String> 타입의 리스트들을 받는 가변인자를 가지고 있음
  • dangerous 메서드 내에서 List<Integer>을 생성하고, 그것을 Object 배열에 할당
  • 배열을 통해 stringLists에 접근하여 List<Integer>를 추가했고 이로 인해 힙 오염(heap pollution)이 발생
  • stringLists에 접근하여 List<Integer>인 요소를 List<String>으로 캐스팅하려고 시도하면 ClassCastException이 발생
  • 힙 오염이 발생하는 이유는 가변인자를 통해 전달된 stringLists 배열이 List<String>의 배열이라는 것을 보장하지 않기 때문
  • 좋은 프로그래밍 실천법은 가변인자(varargs)와 제네릭을 함께 사용하지 않는 것이며, 가능하다면 리스트나 컬렉션을 이용하여 처리하는 것이 더 안전

 

3. 성능 이슈

 

성능에 민감한 상황이라면 가변인수가 걸림돌이 될 수 있습니다.

가변인수 메서드는 호출될 때마다 배열을 새로 하나 할당하고 초기화하기 때문에 상당히 비싼 작업입니다.

다행히 가변인수의 유연성이 필요할 때 선택할 수 있는 패턴이 있습니다.

메서드 호출의 95%가 인수를 3개 이하로 사용한다고 가정했을 때 다음처럼 인수가 0인 것부터 4개인 것까지 총 5개를 정의하고 마지막 다중정의 메서드가 인수 4개 이상인 5%의 호출을 담당하도록 작성하는 방식입니다.


 

EnumSet의 정적 팩터리 of도 위 패턴을 적용해 열거 타입 집합 생성 비용을 최소화하는 것을 볼 수 있습니다.

EnumSet은 비트 필드를 대체하면서 성능까지 보장해야 하기 때문에 아주 적절하게 활용한 예라 할 수 있습니다.

 

 

 

4. 메서드 당 한 개의 가변인수만 사용 가능

 

자바에서는 메서드당 가변인수를 하나만 사용할 수 있습니다.

즉, 한 메서드 시그니처 내에서는 하나의 가변인수 매개변수만 허용되며 반드시 메서드 파라미터의 마지막에 위치해야 합니다.

 

 

정리

메서드의 인수 개수가 일정하지 않을 경우 가변인수를 필요로 하지만, 이에는 몇 가지 주의사항과 제약이 있으므로 신중한 고려 후 적용하는 것이 권장됩니다.

반응형