변수는 타입 기준, 메서드는 객체 기준

상곤·2025년 4월 17일

Java

목록 보기
18/22
post-thumbnail

Java에서 상속 관계를 다루다 보면, 이런 궁금증이 생긴다.

왜 같은 객체를 가리키는데, 변수랑 메서드 호출 결과가 다르지?
그래서 정리한다! (정확히는 내가 헷갈려서 정리한다..🫠)
그 이유는 간단하다.
자바는 변수와 메서드를 호출할 때 기준이 다르기 떄문이다.

  • 변수는 타입 기준으로 결정된다.
  • 메서드는 객체 기준으로 결정된다.

아래의 코드를 보고 이해해보자.

Class

class B {
    int x = 1;
    int getX() {
        return x * 2;
    }
}

class D extends B {
    int x = 2;
    int getX() {
        return x * 3;
    }
}

Main

public class Main {
    public static void main(String[] args) {
        B a = new D();  // 부모 타입 참조, 자식 객체
        D b = new D();  // 자식 타입 참조, 자식 객체

        System.out.print(a.getX() + a.x + b.getX() + b.x);
    }
}

이 때 결과가 어떻게 될까?

15가 나와야 한다.

a.getX() + a.x + b.getX() + b.x
 2 * 3   +  1  +  2 * 3   +  2  = 15

즉, a.x는 1이 나와야 한다.

변수는 타입 기준

a는 B a = new D();로 업캐스팅된 상태다.

참조 변수의 타입이 B이고,
클래스의 변수를 호출할 때는 참조 변수의 타입이 무엇을 호출할지 결정하기 때문에
B Class의 인스턴스 변수 1이 나오는 것이다.

이게 바로 변수는 타입 기준이라는 의미다.

메서드는 객체 기준

반면에 메서드를 호출할 때는,
객체를 기준으로 호출하게 된다.

a가 가리키는 객체는 실제로 new D()로 생성된 D 객체다.
그래서 오버라이딩 된 D Class의 getX() 메서드를 호출하는 것이다.

이게 바로 메서드는 객체 기준이라는 의미다.

왜 이런 차이가 생길까?

여기서 정적 바인딩과 동적 바인딩 개념이 등장한다.

바인딩이란?

어떤 변수나 메서드가 메모리의 무엇을 가리킬지 결정하는 것을 말한다.

  • 정적 바인딩(static binding): 컴파일할 때 이미 결정된다.
  • 동적 바인딩(dynamic binding): 프로그램이 실행될 때 결정된다.

정적 바인딩(변수)

변수는 단순히 "값"을 담고 있는 데이터다.
복잡한 실행 로직이 없고, 빠른 처리가 중요하기 때문에
컴파일할 때 "이 타입의 변수를 가져오자"고 미리 결정해버린다.
그래서 변수는 타입 기준으로 동작하는 것이다.

즉, 컴파일러가 B 타입의 x를 미리(컴파일 시점에) 찾아서 고정시켜놓는다.

동적 바인딩(메서드)

메서드는 실행할 때 진짜 객체의 동작을 실행해야 한다.
(다형성(polymorphism)을 위해서)
그래서 메서드는 실행 시점에 "진짜 객체 타입이 뭐지?"를 확인하고,
그 객체에 맞는 메서드를 찾아 호출한다.

그래서 메서드는 객체 기준 동작한다.

profile
🫠

0개의 댓글