Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java Varargs 메서드 오버로딩 시 발생하는 모호성 오류 완벽 정리

Java에서 가변 인수(varargs)를 사용하다 보면 모호성(ambiguity) 문제가 발생할 수 있습니다. 이는 서로 다른 두 개의 오버로딩된 메서드가 모두 전달된 인수 값으로 호출하기에 유효한 경우에 생기며, 이때 컴파일러는 어떤 메서드를 호출해야 할지 판단하지 못해 컴파일 오류를 발생시킵니다.

예제 코드

아래 예제에서는 double 타입과 boolean 타입의 varargs를 각각 받는 두 개의 my_fun 메서드를 오버로딩하여 모호성 상황을 확인해 봅니다.

public class Demo {
   static void my_fun(double ... my_Val){
      System.out.print("fun(double ...): " + "Number of args: " + my_Val.length );
      for(double x : my_Val)
         System.out.print(x + " ");
      System.out.println();
   }
   static void my_fun(boolean ... my_Val){
      System.out.print("fun(boolean ...) " + "The number of arguments: " + my_Val.length);
      for(boolean x : my_Val)
         System.out.print(x + " ");
      System.out.println();
   }
   public static void main(String args[]){
      my_fun(11.56, 34.78, 99.09, 56.66);
      System.out.println("Function 1 has been successfully called");
      my_fun(true, false, true, false);
      System.out.println("Function 2 has been successfully called");
      my_fun();
      System.out.println("Function 3 has been successfully called");
   }
}

컴파일 결과

Demo.java:23: error: reference to my_fun is ambiguous
my_fun();
^
both method my_fun(double...) in Demo and method my_fun(boolean...) in Demo match
1 error

코드 동작 방식

Demo 클래스에는 'my_fun'이라는 이름의 메서드가 정의되어 있으며, 이 메서드는 개수에 제한 없이 double 타입의 부동소수점 값을 받습니다. 전달받은 값들은 for 루프를 통해 콘솔에 출력됩니다. 같은 이름의 메서드가 boolean 타입의 가변 인수를 받는 형태로 오버로딩되어 있으며, 역시 for 루프를 사용해 결과를 출력합니다.

main 메서드에서는 먼저 my_fun을 부동소수점 값으로 호출하고, 그다음 boolean 값으로 호출합니다. 앞의 두 호출은 인수의 타입이 명확하기 때문에 아무 문제 없이 처리됩니다. 하지만 세 번째 호출처럼 인수 없이 my_fun()을 호출하면 double... 버전과 boolean... 버전 중 어느 쪽도 우선순위를 가질 수 없어, 컴파일러가 모호성 오류를 발생시키며 빌드가 실패합니다.

왜 모호성이 발생할까?

컴파일러는 메서드 호출 시 다음 단계를 거쳐 적합한 오버로딩을 찾습니다.

  • 1단계: 박싱·확장 변환 없이 정확히 일치하는 메서드 탐색
  • 2단계: 기본형 확장 또는 오토박싱을 통한 매칭 시도
  • 3단계: 마지막으로 varargs 확장을 고려

문제는 인수가 하나도 없는 my_fun() 호출입니다. 어떤 타입 힌트도 제공되지 않기 때문에 double...과 boolean... 두 오버로딩이 동등하게 적합해지고, Java 컴파일러는 임의로 선택하지 않고 'reference is ambiguous' 오류를 내며 컴파일을 거부합니다.

모호성 해결 방법

  • 인수 없는 호출 피하기: 최소 한 개 이상의 명시적 인수를 전달하거나, 인수 없는 호출을 위한 별도의 오버로딩을 정의합니다.
  • 명시적 캐스팅: my_fun(new double[]{})처럼 배열을 직접 생성해 타입을 분명히 지정합니다.
  • 메서드 이름 구분: 오버로딩 대신 printDoubles(), printBooleans()처럼 서로 다른 이름의 메서드를 사용합니다.
  • 설계 단계 점검: varargs 오버로딩을 설계할 때는 모든 호출 형태에서 유일한 메서드가 선택되는지 반드시 검토해야 합니다.

정리하면, varargs를 활용한 메서드 오버로딩은 코드를 간결하게 만들어 주지만, 인수 없는 호출이나 타입이 불분명한 호출이 포함되면 모호성 오류가 발생하기 쉽습니다. 각 호출이 항상 하나의 메서드로만 해석되도록 신중하게 설계하는 것이 안전합니다.