티스토리 뷰
가변인수 (varargs) 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있다.
가변인수 메서드 호출 시 인수의 개수와 길이가 같은 배열을 만들고 인수들을 이 배열에 저장하여 가변인수 메서드에 건네준다.
// 가변인수 사용법
static int sum(int... args) {
int sum = 0;
for (int arg : args) {
sum += args;
}
return sum;
}
예를 들어 최솟값을 구하는 메서드를 작성한다면 인수가 1개 이상이어야 하는데 0개도 받을 수 있게 설계하면 에러가 날 수 있다.
// BAD - 인수가 1개 이상이어야 할 때 가변인수 사용법
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;
}
그래서 이런식으로 0개를 받으면 IllegalArgumentException 를 던지게 했다.
근데 이 책에서 계속 말하듯 오류는 빨리 잡아야하는데 이런식으로 하면 런타임에 실패한다.
거기다 코드도 지저분하다. 다른 방법을 사용하자.
// GOOD - 인수가 1개 이상이어야 할 때 가변인수 사용법
static int min(int firstArg, int... remainingArgs) {
int min = firstArg;
for (int arg : remainingArgs) {
if (arg < min) min = arg;
}
return min;
}
이렇게 첫 번째로는 평번한 매개변수를 받고, 가변인수를 두 번째로 받으면 문제가 깔끔히 사라진다.
이렇듯 가변인수는 인수 개수가 정해지지 않았을때 아주 유용하게 사용할 수 있다.
가변인수는 앞에서 말했듯 호출될 때마다 배열을 새로 하나 할당하고 초기화한다. 그래서 성능에 민감할때 문제가 될 수 있다. 다행히 유연성이 필요할 때 선택할 수 있는 패턴이 있다.
public void method1() {}
public void method1(int a1) {}
public void method1(int a1, int a2) {}
public void method1(int a1, int a2, int a3) {}
public void method1(int a1, int a2, int a3, int... rest) {}
예를 들어 메소드 호출의 95% 정도가 인수를 3개 이하로 쓴다면 이런식으로 다중정의하는 것이다.
95% 호출은 가변인수를 사용하지 않아 배열을 생성하지 않고 5% 호출만 배열을 생성하는 것이다.
// EnumSet
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;
}
Java API 중 EnumSet이 이 기법의 좋은 예시이다.
결론
- 인수 개수가 일정하지 않은 메서드를 정의한다면 가변인수가 반드시 필요하다.
- 메서드 정의시 필수 매개변수는 가변인수 앞에 두자.
- 가변인수 사용시 성능문제도 고려해보자.
'책 > 이펙티브자바' 카테고리의 다른 글
아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용하라 (0) | 2021.09.17 |
---|---|
아이템 54. null이 아닌, 빈 컬렉션이나 배열을 반환하라 (0) | 2021.09.17 |
아이템 60. 정확한 답이 필요하다면 float와 double은 피하라 (0) | 2021.09.16 |
아이템 59. 라이브러리를 익히고 사용하라 (0) | 2021.09.16 |
아이템 52. 다중정의는 신중히 사용하라 (0) | 2021.09.16 |
링크
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- JS 딥다이브
- Spring Security
- 드림코딩
- REST API
- js promise
- http
- 김영한 JPA
- 이펙티브자바
- 킹수빈닷컴
- js api
- js array
- 프로그래머스 SQL
- 백기선 스터디
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초
- 패스트캠퍼스 컴퓨터공학 완주반
- ㅇㄷㅇㅈ
- 모던자바스크립트
- HTTP 완벽가이드
- 이펙티브자바 아이템59
- HTTP 완벽 가이드
- java
- 백준
- 프로그래머스
- 김영한 http
- 이펙티브자바 스터디
- 이펙티브자바 아이템60
- GCP
- JPA 연관관계 매핑
- BOJ
- dreamcoding
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
글 보관함