원본 글: https://www.baeldung.com/java-varargs
Java5에서 도입된 Varargs는 가변 인자를 의미하는데, 이는 하나의 메서드가 매개변수로 여러 개의 값을 받을 수 있게 해주는 기능입니다.
이 글에서는 어떻게 사용할 수 있는지 학습합니다.
1. Before Varargs
Java5 이전에는 임의 갯수를 가지고 있는 인자 값을 넘기려면 배열형태로 넘기거나 N개의 함수를 오버본 글: https://www.baeldung.com/java-varargs
Java5에서 도입된 Varargs는 가변 인자를 의미하는데, 이는 하나의 메서드가 매개변수로 여러 개의 값을 받을 수 있게 해주는 기능입니다.
이 글에서는 어떻게 사용할 수 있는지 학습합니다.
1. Before Varargs
Java5 이전에는 임의 갯수를 가지고 있는 인자 값을 넘기려면 배열형태로 넘기거나 N개의 함수를 오버로딩 하여 사용했습니다.
public String format() { ... }
public String format(String value) { ... }
public String format(String val1, String val2) { ... }
2. Use of Varargs
Varargs는 내부 구현이 배열로 되어있어서 위와같은 불필요한 코드작성을 안할 수 있게 도와줍니다.
public String formatWithVarArgs(String... values) {
// ...
}
이런식으로 구성할 수 있습니다.
formatWithVarArgs();
formatWithVarArgs("a", "b", "c", "d");
호출은 이런식으로 호출할 수 있습니다.
앞서 말했듯이 varargs는 배열로 구성되어있기에 일반 배열처럼 조작해줘야합니다.
3. Rules
varargs를 제대로 사용하기위해서는 몇 가지 규칙들을 지켜줘야합니다.
- 각 함수는 하나의 varargs파라미터만 가질 수 있습니다.
- varargs 인수는 반드시 마지막에 선언되어야합니다.
4. Heap Pollution
varargs를 사용하면 Heap오염이라는 것을 발생시킬 수 있습니다. 다음과 같은 예제를 확인해봅니다.
@Test
public void heap_pollution_test() {
//String one = firstOfFirst(Arrays.asList("one", "two"), Collections.emptyList());
Assertions.assertThrows(ClassCastException.class, () -> {firstOfFirst(Arrays.asList("one", "two"), Collections.emptyList());});
//기대하던 결과
//Assertions.assertEquals("one", one);
}
public static String firstOfFirst(List<String>... strings) {
List<Integer> ints = Collections.singletonList(42);
Object[] objects = strings;
objects[0] = ints; // Hepa pollution
return strings[0].get(0); //ClassCast Exception
}
이 코드는 예외를 발생시킵니다.
4.1 Safe Usage
varargs를 사용하면 Java 컴파일러는 함수에 주어진 파라미터를 기준으로 배열을 생성합니다.
만약 제네릭 타입으로 varargs를 사용하게 되면 Runtime Exception을 마주할 수 있습니다. 자바 컴파일러는 이런 문제를 미리 방지하기 위해 unsafe varargs usage라는 경고를 표시해줍니다.
그렇기에 varargs를 안전하게 사용하려면 다음과 같은 방식을 따라야합니다.
- 암묵적으로 만들어진 배열에 대해서는 값을 저장하지 않습니다.
- 생성된 배열에 대한 참조가 함수를 벗어나지 않게 합니다.
만약 함수 자체가 안전하다고 판단된다면 @SafeVarargs 어노테이션을 통해서 경고문을 무시할 수 있습니다.
간단히 말하자면 varargs는 그냥 값 전달용으로만 사용하고 수정을 하는 등의 작업은 지양하는편이 좋습니다.
4.2 Escaping Varargs Reference
varargs를 안전하지 사용하지 않는 또 다른 예시를 봅니다.
static <T> T[] toArray(T... arguments) {
return arguments;
}
얼핏보면 위 함수는 전혀 문제가 될 것이 없어 보입니다.
그러나 return 구문을 통해서 varargs를 사용한 배열을 전달하고 있으므로 2번째 규칙에 어긋납니다.
왜 위 코드가 위험한지 다음 함수를 통해서 확인합니다.
static <T> T[] returnAsIs(T a, T b) {
return toArray(a, b);
}
String[] args = returnAsIs("One", "Two");
이 코드는 결국 ClassCastException을 발생시킵니다. returnAsIs()함수에서 어떤 동작이 일어나는지 확인해봅니다.
- toArray() 함수에서 a,b를 넘깁니다. 이때 자바는 배열을 생성하려고합니다.
- Object[]타입은 모든 유형을 저장할 수 있으므로 컴파일러는 이 배열을 생성합니다.
- toArray() 는 Object[]을 리턴합니다.
- 함수를 호출한 곳에서는 String[] 배열형태로 받고 있는데 Object[]형을 넘기기에 ClassCastException을 발생시킵니다.
5. 결론
Varargs를 사용하면 많은 보일러플레이트 코드를 제거할 수 있습니다.
그리고 autoboxing을 통하여 코드를 작성하는데 많은 도움을 줄 수 있습니다.
'Baeldung번역&공부 > Java-basic' 카테고리의 다른 글
hashCode()란 (0) | 2025.02.10 |
---|---|
Pass-By-Value메커니즘 설명(Pass-By-Value as a Parameter Passing Mechanism in Java) (0) | 2025.02.08 |
문자열 잇는 방법(String Concatenation in Java) (0) | 2025.02.08 |
패키지에 대하여(Guide to Java Packages) (0) | 2025.02.04 |
Java main() Method Explained (0) | 2025.02.03 |