가변 인수에 대한 내용은 자바스크립트를 공부하면서 rest 파라미터에 대한 내용으로 알고 있었다.
자바를 사용해 개발을 진행할 때는 잘 사용하지 않는 기능이였는데, 최근 자바에 대한 공부를 진행하면서 관련 내용이 있어 정리하려고 한다.
사실 가변인수에 대한 내 생각은 부정적이다. 그 이유는 바로 모호함이다.
모호함은 프로그래머를 고생시킨다.
가변 인수를 사용할 수 있는 메서드를 정의했다고 해도 이를 사용하는 측에서는 반드시 확인을 하게 된다.
모호하게 가변적으로 인수를 더 받을 수 있는 것보단 확실하게 파라미터 정의를 통해 알려주는 쪽이 좋다고 생각한다.
물론 이를 위해 메소드 오버 로딩 등 코드의 중복이 발생할 수 있지만 모호함으로 인해 발생하는 사이드 이펙트를 생각해보면 더 좋은 코드가 아닐까 생각한다.
가변 인수는 클라이언트에서 인수의 개수를 조절할 수 있는 기능이다.
해당 가변인수를 사용한 메서드를 호출하면 정의된 타입을 가진 배열이 자동적으로 만들어 진다.
가변 인수를 활용한 메서드는 ClassCastException이 발생할 여지가 있습니다. 이는 Heap Pollution이라고 하는 과정입니다.
Heap Pollution
Java generic type에서 변수화 된 타입이 가리키는 오브젝트의 타입이 해당 변수화 된 타입의 타입과 다를 때를 의미한다.
public class HeapPollutionDemo {
public static void main(String[] args) {
Set s = new TreeSet<Integer>();
Set<String> ss = s; // unchecked warning
s.add(new Integer(42)); // another unchecked warning
Iterator<String> iter = ss.iterator();
while (iter.hasNext()) {
String str = iter.next(); // ClassCastException thrown
System.out.println(str);
}
}
}
이 는 실제 형 변환을 하여 가변 인수의 타입과 변환되는 타입이 일치되지 않는 경우가 아니더라도 발생합니다.
public void varargs(List<String>... stringArgs){
Object[] object = stringArgs; //Object 배열에 가변인수 배열 할당.
object[0] = List.of(1,2,3); //가변인수가 데이터전달을 하지 않고 타입이 변환된 채로 재할당(heap pollutin)
String result = stringArgs[0].get(0); // 가변인수 배열이 이중 배열구조로 되어 요소 취득
}
타입이 변하지 않는 코드로 보이지만 제네릭은 실체화되지 않는다. 컴파일 시점에 이는 형 변환이 이루어지게 되는데
이 과정에서 ClassCastException이 발생한다.
물론 정확한 가변 인수에 대한 타입 캐스팅 없이 안전하게 사용한다면 매우 좋은 기능이 될 수 있습니다.
실제 매우 편리한 기능이기도 합니다.
제네릭 가변 인수를 가진 메서드를 작성했다면 호출자에게 알려주는 방법도 매우 좋은 것 같습니다.
만약 해당 메서드가 정말 type-safe 하다면 자바 7에서 나온 @SafeVarargs 에노 테이션을 통해 호출자 쪽에서 발생하는 경고를 숨길 수 있습니다.
그럼 type-safe 한 가변 인수 메서드의 조건은 뭘까요?
- 가변 인수 배열의 참조값을 외부로 반환하지 않는다. 오류에 범위가 커질 수 있는 부분으로 보입니다.
- 단순 데이터 전달
즉 해당 가변 인수를 통해 복잡한 무언가를 하지 않고 호출자의 의도가 단순히 전달을 위해서만 사용한다면 이는 type-safe 해질 수 있습니다.
이를 활용하는 특정 예시는 setter가 있을 수 있을 것 같네요.
자바 빈인 경우 말고 빌더 패턴을 이용하는 경우 필수 값 외에 가변 인수를 통해 추가적인 작업을 해줄 수 있을 것 같습니다.
하지만 setter를 사용하는 외부 라이브러리들이 많은 경우에는 적합하지 않아 보입니다. 여러 계층적인 구조로 복잡한 클래스의 인스턴스를 생성할 때 하위 타입의 빌더에서 필요에 따라 구현하는 방법도 생각해보았습니다.
근데 이 방법 말고도 더 좋은 방법이 있을 것 같습니다. 인스턴스를 만들 때 어떠한 변형을 가하는 것이 의미 있는 메서드 네이밍을 통해 변형을 가하는 것보다 좋다고는 생각할 수 없을 것 같습니다.
코드의 수를 줄인다?, 가변 인자라 생성 시 필수 값을 강제하지는 못할 것 같고, 이는 뭔가 의도를 숨기는 역할을 할 수도 있겠다는 생각이 드네요.
일단 가벼운 프로젝트에 적용해서 사용해보아야겠습니다
'JAVA' 카테고리의 다른 글
S3 다중 업로드를 병렬로 처리 시 발생할 수 있는 문제..(CountDownLatch) (0) | 2022.12.03 |
---|---|
keytool (0) | 2022.11.14 |
JDK Dynamic Proxy (0) | 2022.01.22 |
Server Networking Proxy (0) | 2021.11.14 |
메일 발송 (0) | 2021.11.06 |
댓글