티스토리 뷰

제네릭(Generic)과 메소드 오버로딩(Overloading)은 자바에서 자주 사용하되는 강력한 기능 중 하나입니다. 하지만 이 두가지가 결합될 때, 컴파일 시점과 런타임 시점에서의 동작 방식에 차이가 생깁니다. 이번 포스팅에서는 간단한 예제를 통해 그 차이를 알아보겠습니다.

 

제네릭 : 컴파일 시점에 타입을 지정하지 않고, 런타임에 구체적인 타입이 확정되는 방식으로 타입 안정성을 보장합니다.
오버로딩 : 같은 이름의 메서드를 매개변수의 타입이나 개수에 따라 여러 개 정의하고, 호출 시점에 적합한 메서드를 선택하는 기능입니다.

 

1. 예제 코드

class GenericOverloadingExample {
    public static void main(String[] args) {
        new Container<>(42).display();  // Integer 타입
        new Container<>("Hello").display();  // String 타입
    }

    public static class Container<T> {
        T value;

        public Container(T value) {
            this.value = value;
        }

        public void display() {
            new Handler().handle(value);
        }

        class Handler {
            void handle(Integer num) {
                System.out.println("Integer handling: " + num);
            }

            void handle(String str) {
                System.out.println("String handling: " + str);
            }

            void handle(Object obj) {
                System.out.println("Object handling: " + obj);
            }
        }
    }
}

 

2. 코드 설명

  • Container<T> 클래스:
    • 제네릭 클래스로, T 타입의 값(value)을 저장하고 이를 처리하는 메서드를 제공합니다.
    • display() 메서드는 Handler 클래스의 handle() 메서드를 호출해 value를 처리합니다.
  • Handler 클래스: handle() 메서드는 오버로딩된 세 가지 메서드를 포함합니다 .
    • handle(Integer num): Integer 타입을 처리합니다.
    • handle(String str): String 타입을 처리합니다.
    • handle(Object obj): 그 외 모든 Object 타입을 처리합니다.

 

3. 실행 결과

Object handling: 42
Object handling: Hello
  • 컴파일 시점: 컴파일러는 제네릭 타입 T를 정확하게 알지 못하기 때문에 이를 Object로 취급합니다. 따라서 오버로딩된 메서드 중 가장 일반적인 handle(Object) 메서드를 선택합니다.
  • 런타임 시점: 실제로 실행할 때는 T의 구체적인 타입이 결정되지만, 이미 컴파일 시점에 선택된 메서드가 호출되기 때문에 **오버로딩된 다른 메서드들 (handle(Integer), handle(String))**은 호출되지 않습니다.

 

4. 결론

제네릭과 오버로딩이 결합된 경우, 호출되는 메서드는 컴파일 시점에 결정됩니다. 이때 컴파일러는 제네릭 타입 T를 정확히 알 수 없으므로, T를 가장 일반적인 타입인 Object로 간주합니다. 결과적으로, 제네릭 타입이 어떤 구체적인 타입으로 확정되더라도, 컴파일 시점에 선택된 메서드인 print(Object a)가 항상 호출되게 됩니다. 

 

감사합니다.

 

 

최근에 올라온 글
Total
Today
Yesterday