
1. 정적 바인딩 vs 동적 바인딩 – "자바에서 진짜 실행되는 건 뭘까?"
자바에서 객체를 다룰 때, 우리가 쓰는 메서드는 언제, 어떤 기준으로 결정되는 걸까?
부모 타입 변수로 자식 객체를 참조했을 때, 과연 호출되는 메서드는 누구 걸까?
이때 나오는 개념이 바로 "정적 바인딩"과 "동적 바인딩"이다.
1-1. 바인딩이란?
바인딩(binding)은 쉽게 말해
"이 메서드 호출은 실제로 어떤 코드와 연결되어 있는가?" 를 말한다.
이 연결이 컴파일할 때 정해지면 → 정적 바인딩,
프로그램 실행 중에 정해지면 → 동적 바인딩이라고 한다.
1-2. 정적 바인딩 (Static Binding)
- 컴파일할 때 호출할 메서드가 결정됨
- 주로 static, final, private 메서드에서 발생함
- 변수나 메서드 이름만 보고 컴파일러가 바로 결정하는 것
class Parent {
static void hello() {
System.out.println("👴 부모 hello");
}
}
class Child extends Parent {
static void hello() {
System.out.println("👶 자식 hello");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
p.hello(); // 출력: 부모 hello
}
}왜 부모 메서드가 실행될까?
→ hello()가 static이기 때문! 컴파일러는 p가 Parent 타입인 걸 보고
Parent.hello()를 호출하기로 컴파일 단계에서 결정해버리기 때문이다.
1-3. 동적 바인딩 (Dynamic Binding)
- 실행 중에 실제 객체의 타입을 보고 호출할 메서드가 결정됨
- 자바의 오버라이딩 + 다형성 덕분에 가능
- 주로 @Override된 인스턴스 메서드에서 발생함
class Parent {
void hello() {
System.out.println("👴 부모 hello");
}
}
class Child extends Parent {
@Override
void hello() {
System.out.println("👶 자식 hello");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
p.hello(); // 출력: 자식 hello
}
}왜 자식 메서드가 실행될까?
→ hello()는 인스턴스 메서드이고, 실제 객체는 Child이기 때문이다.
자바는 실행 시점에 p가 어떤 객체인지 확인하고, 자식 객체면 자식의 오버라이딩된 메서드를 호출한다.
이게 바로 동적 바인딩이다.
2. "앞에 선언된 타입을 따라가는가" ?
C언어는 Yes, 자바는 No
자바는 "선언된 타입"보다 "실제 객체"를 따라가고,
C는 "선언된 타입"만 따르는 정적인 언어이다.
2-1. 자바 (Java): 다형성(Polymorphism) + 동적 바인딩
class Parent {
void hello() { System.out.println("I'm your father."); }
}
class Child extends Parent {
void hello() { System.out.println("I'm your son."); }
}
public class Main {
public static void main(String[] args) {
Parent p = new Child(); // 선언은 Parent지만
p.hello(); // 실행은 Child의 hello()! ✅
}
}✅ 실제 객체가 누구냐에 따라 실행되는 메서드가 결정됨 → 동적 바인딩
2-2. C 언어: 정적 타입 시스템 + 구조체 기반
C는 객체지향이 아니므로 "상속"이나 "다형성"이 없다.
struct Person {
int age;
};
struct Student {
int age;
int grade;
};
void printAge(struct Person p) {
printf("%d\n", p.age);
}int main() {
struct Student s = {20, 3};
printAge(s); // ❌ 구조체는 완전히 다른 타입이므로 이렇게 못 넘김
}C에서는 앞에 선언된 타입이 전부이다.
구조체 간 변환은 암시적으로 안 되고, 타입이 다르면 함수 호출도 안 된다.
✅ 한 마디로 C언어는 "앞에 있는 타입대로만 작동" 하는 언어이다.
3. 예시
다음 JAVA 언어 프로그렘의 출력 결과를 쓰시오.
class Person {
protected String name; // protected로 변경하면 자식 클래스 접근 가능
public Person(String n) {
name = n;
}
public void whoRU() {
System.out.println(name + "입니다.");
}
}
class Student extends Person {
String school;
public Student(String n, String s) {
super(n);
school = s;
}
public void whoRU() {
System.out.println(school + " 학교에 다니는 " + name + "입니다.");
}
}
public class People {
public static void main(String[] args) {
Person obj = new Student("이흥직", "수일중");
obj.whoRU(); // 동적 바인딩으로 Student의 whoRU가 호출됨
}
}수일중학교에 다니는 이흥직입니다.- Person obj = new Student(...) 형태는 업캐스팅(upcasting) 이지만,
- whoRU()는 Person에 있는 오버라이딩 메서드이므로,
- 실제 객체가 Student면 Student.whoRU()가 호출된다. - 자바의 다형성(polymorphism)
자바에서는 앞에 선언된 타입이 Person이더라도, 실제 객체가 Student이면 Student의 오버라이딩된 메서드가 호출된다.
Person obj = new Student("이흥직", "수일중");
obj.whoRU(); // ✅ 이건 Student의 whoRU()가 호출된다.obj는 Person 타입으로 선언되었지만, 실제로는 new Student(...)로 Student 객체를 생성했기 때문에,
메서드 호출 시, 자식 클래스(Student)의 오버라이딩된 실제 객체의 메서드가 실행되는 것이다.
이걸 "동적 바인딩(dynamic binding)" 또는 "런타임 바인딩" 이라고 한다.
💡 "앞에 Person이니까 부모 메서드가 실행돼야 한다"는 건 C언어와 같은 정적 바인딩 기준이다.
4. 자식 객체지만 부모의 메서드가 실행되는 경우
물론 "자식 객체지만 부모의 메서드가 실행되는 경우"도 존재한다.
그 경우는 주로 다형성/오버라이딩이 아닌 상황에서 발생한다. 아래와 같다.
- 오버라이딩이 아닌 경우 (메서드가 자식에 없음)
- 자식에서 super 키워드로 부모 메서드 호출
- 정적(static) 메서드는 오버라이딩이 아니라 하이딩(hiding)
'정보처리기사' 카테고리의 다른 글
| 응집도와 결합도 에 대해 알아보자 (3) | 2025.05.15 |
|---|---|
| [서브넷] 네트워크 주소 구하는 법 (정보처리기사 실기 25년 1차) (1) | 2025.05.13 |
| [C언어] 포인터, Call by Reference, 2차원 배열 행 대표주소, 구조체 정리 (0) | 2025.04.19 |
| [C언어] 변수의 유효범위, 논리연산자, 증감연산자, static 변수, global 변수 주의사항 정리 (3) | 2025.04.10 |
| [2024년 3회] 정보처리기사 실기 복원 문제 해설 (이건 누가 낸 문제야?🤯) (6) | 2025.04.07 |