개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

공부 › Java › 클래스와 객체

다형성과 메서드 선택

어느 메서드가 실행될지는 누가, 언제 정하나

변수의 선언 타입과 실제 들어 있는 객체의 타입이 다를 수 있습니다. 오버라이딩한 메서드는 실행 시점에 실제 객체를 보고 고르지만, 오버로딩, static 메서드, 필드는 컴파일 시점에 선언 타입만 보고 정해집니다.

실행으로 대조 · JDK 21에서 모든 조합을 컴파일·실행해 대조

이 실습에 나오는 개념

다형성
같은 타입의 참조로 같은 메서드를 호출해도 실제 객체의 종류에 따라 다른 동작이 실행되는 성질이다. 상위 타입(인터페이스나 상위 클래스) 변수에 여러 하위 타입 객체를 담을 수 있고, 어떤 구현이 실행될지는 실행 시점에 결정된다(동적 바인딩). 호출하는 코드를 바꾸지 않고 새로운 구현을 추가할 수 있게 해 준다.
오버라이딩
상위 클래스(또는 인터페이스)의 메서드를 하위 클래스에서 같은 시그니처로 다시 정의하는 것이다. 실행 시점에 실제 객체의 타입에 맞는 메서드가 호출되어 다형성을 구현한다. 접근 범위를 더 좁힐 수 없고, static·private·final 메서드는 오버라이딩할 수 없다.
오버로딩
같은 이름의 메서드를 매개변수의 개수나 타입을 다르게 해서 여러 개 정의하는 것이다. 어떤 메서드가 호출될지는 컴파일 시점에 인자의 타입을 보고 결정된다. 반환 타입만 다른 것은 오버로딩이 아니며 컴파일 오류다.
static
인스턴스가 아니라 클래스에 속하는 멤버임을 나타내는 키워드다. static 필드는 클래스당 하나만 존재해 모든 인스턴스가 공유하고, static 메서드는 객체를 만들지 않고 호출한다. 값이 바뀌는 static 필드는 사실상 전역 변수이므로 여러 스레드가 동시에 접근할 때 문제가 되기 쉽다.
상속
기존 클래스(상위 클래스)의 필드와 메서드를 물려받아 새 클래스(하위 클래스)를 정의하는 것이다. 공통 코드를 재사용하고 하위 클래스에서 필요한 부분만 추가하거나 재정의한다. 자바의 클래스는 단일 상속만 가능하며, 상위 클래스 변경이 하위 클래스 전체에 영향을 주므로 "is-a" 관계가 분명할 때만 쓰는 것이 좋다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 컴파일 시점: Animal a = new Dog(). 변수 a의 선언 타입은 Animal이고, 실행되면 힙에 Dog 객체가 만들어집니다. 둘이 다릅니다.
  2. 컴파일 시점: 컴파일러는 선언 타입 Animal에 sound()가 있는지만 확인합니다. 어느 클래스의 sound()를 실행할지는 정하지 않고 "sound()를 호출하라"는 지시만 남깁니다.
  3. 실행 시점: JVM이 a가 가리키는 실제 객체의 클래스(Dog)를 확인하고, 그 클래스의 sound()를 찾아 실행합니다(동적 바인딩).

실행 결과

코드

class Animal {
    String name = "동물";
    void sound()       { System.out.println("Animal.sound"); }
    static void info() { System.out.println("Animal.info"); }
}
class Dog extends Animal {
    String name = "개";                 // 같은 이름의 필드
    @Override
    void sound()       { System.out.println("Dog.sound"); }
    static void info() { System.out.println("Dog.info"); }
}
class Printer {
    void print(Animal x) { System.out.println("print(Animal)"); }
    void print(Dog x)    { System.out.println("print(Dog)"); }
}

Animal a = new Dog();
a.sound();

이 모형의 전제

모든 조합의 출력은 이 PC의 JDK 21에서 같은 코드를 실제로 컴파일·실행한 결과와 대조했습니다. 변수를 통해 static 메서드를 호출하는 a.info()는 문법상 가능하지만 권장되지 않는 방식이며, 선언 타입 기준으로 정해진다는 점을 보이려고 넣었습니다.

앞 실습: 상속과 오버라이딩 · 다음 실습: 인터페이스와 추상 클래스

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요