Java에서 정적(static) 메서드는 오버로드(overload)가 가능합니다. 다만 한 가지 조건이 있는데, 두 메서드가 오직 static 키워드 유무만으로 구별되는 경우에는 오버로드로 인정되지 않습니다. 즉, 매개변수의 개수나 타입이 달라야 정상적인 오버로드가 됩니다.
오버로드 예제
public class Demo{
public static void test(){
System.out.println("Demo 클래스의 test 함수가 호출되었습니다");
}
public static void test(int val){
System.out.println("매개변수를 가진 Demo 클래스의 test 함수가 호출되었습니다");
}
public static void main(String args[]){
System.out.println("main 메서드에서 Demo의 함수들을 호출합니다");
Demo.test();
Demo.test(57);
}
}실행 결과
main 메서드에서 Demo의 함수들을 호출합니다 Demo 클래스의 test 함수가 호출되었습니다 매개변수를 가진 Demo 클래스의 test 함수가 호출되었습니다
위 예제의 Demo 클래스에는 특정 메시지를 출력하는 test 메서드가 정의되어 있으며, 정수 값을 매개변수로 받는 또 다른 test 메서드도 함께 정의되어 있습니다. 각 메서드 본문 내부에는 해당하는 메시지가 출력되도록 작성되어 있습니다. main 메서드에서는 test 메서드를 매개변수 없이 한 번, 정수 매개변수와 함께 한 번 호출하며, 그 결과 콘솔에 각각 대응되는 메시지가 출력됩니다. 이처럼 매개변수 시그니처가 다르면 같은 이름의 정적 메서드도 문제없이 공존할 수 있습니다.
정적 메서드는 오버라이드할 수 없다
반면, Java에서 정적 메서드는 오버라이드(override)할 수 없습니다. 하위 클래스에서 상위 클래스와 동일한 시그니처를 가진 정적 메서드를 정의하는 것은 가능하지만, 이는 런타임 다형성(runtime polymorphism)으로 동작하지 않습니다. 이러한 현상을 흔히 '메서드 하이딩(method hiding)'이라고 부르며, 실제 오버라이딩과는 다릅니다. 다음 예제를 통해 확인해 보겠습니다.
오버라이드 예제
class base_class{
public static void show(){
System.out.println("상위 클래스의 정적(클래스) 메서드입니다");
}
public void print_it(){
System.out.println("상위 클래스의 비정적(인스턴스) 메서드입니다");
}
}
class derived_class extends base_class{
public static void show(){
System.out.println("하위 클래스의 정적(클래스) 메서드입니다");
}
public void print_it(){
System.out.println("하위 클래스의 비정적(인스턴스) 메서드입니다");
}
}
public class Demo{
public static void main(String args[]){
base_class my_instance = new derived_class();
System.out.println("상위 클래스 타입의 인스턴스가 생성되었습니다.");
my_instance.show();
System.out.println("show 함수 호출 완료");
my_instance.print_it();
System.out.println("print_it 함수 호출 완료");
}
}실행 결과
상위 클래스 타입의 인스턴스가 생성되었습니다. 상위 클래스의 정적(클래스) 메서드입니다 show 함수 호출 완료 하위 클래스의 비정적(인스턴스) 메서드입니다 print_it 함수 호출 완료
상위 클래스인 base_class에는 메시지를 출력하는 정적 메서드 show와, 마찬가지로 메시지를 출력하는 일반(비정적) 메서드 print_it가 정의되어 있습니다. derived_class는 이 상위 클래스를 상속받아 두 메서드를 모두 재정의합니다. 그리고 Demo 클래스의 main 메서드에서는 상위 클래스 타입의 참조 변수로 하위 클래스 타입의 객체를 생성하여 두 메서드를 호출합니다.
여기서 주목해야 할 점은 실행 결과의 차이입니다. 비정적 메서드인 print_it는 실제 객체의 타입(하위 클래스)을 기준으로 호출되어 하위 클래스의 메서드가 실행됩니다. 이것이 바로 런타임 다형성입니다. 반면 정적 메서드인 show는 참조 변수의 타입(상위 클래스)을 기준으로 컴파일 시점에 바인딩되기 때문에 상위 클래스의 메서드가 실행됩니다. 이처럼 정적 메서드는 객체가 아닌 클래스에 속하기 때문에 다형적 동작이 불가능하며, 따라서 진정한 의미의 오버라이딩은 성립하지 않습니다.