[Java] Binding
개요
카카오 테크 캠퍼스 3기를 진행하면서, Reflection 에 대해 공부를 하면서 Dynamic Binding 이란 단어가 나와, 해당 개념은 어떤 개념일까? 라는 궁금증이 생겨 이렇게 포스팅까지 진행하게 되었다.
내용
Binding
우선 정적 바인딩과 동적 바인딩을 배우기 전 한 가지 사실에 대해서 알아야 한다. 과연 바인딩 ( Binding ) 이란 무엇일까?
사전적인 정의를 먼저 얘기하자면
프로그램의 기본 단위가 가질 수 있는 구성요소의 구체적인 값 성격을 확정하는 것
Binding 이라고 부르는 또 다른 예시들이 있는데, 한번 살펴보자.
- Computer Programming 에서 각종 값들이 확정되어서, 더 이상 변경할 수 없는 상태가 되는데→ 이 상태를 Binding 상태라고 한다.
- Program 내에서 변수, 배열, Label, 절차 등의 명칭→ 식별자 ( Identifier ) 가 그 대상인 Memory 주소, Data 형, 실제 값으로 배정되는 것
- 프로그래머가 코딩을 해서 Compile 을 하게 되면, 프로그래머가 값을 변경할 수 없는 상태가 되는 것→ Memory 에 값을 할당하는 것 또한 Binding 이다.
위와 같은 모든 것들이 Binding 으로 포함이 된다. ( 한국말로 구속하다 라는 의미를 갖고 있는데 비슷한 느낌으로 사용되는 것 같다 )
이 Binding 에는 2가지의 종류가 있다.
- static binding ( 정적 바인딩 )
- dynamic binding ( 동적 바인딩 )
private, final, static 멤버에 대해서는 Static Binding 을 사용하는 반면 가상 Method 에 대해서는 Binding 은 Runtime 객체에 기반하여 Runtime 중에 수행을 한다!
Java 에서는 Method 가 기본적으로 가상 Method 이다.
- 추후에 가상 Method 에 대해서 설명을 하고자 한다.
Static Binding 은 바인딩을 위해서 유형 정보를 사용하고, Overload 된 메서드는 Static Binding 을 사용한다. 같은 이름의 Method 가 여러 개 있는 경우에 어떤 Method 를 호출할 지 결정한다.
Dynamic Binding 은 바인딩을 확인하기 위해서 객체를 사용하고, Override 된 메서드는 Dynamic Binding 을 사용하여 Runtime 중에 해결할 수 있다.
Static binding
Compiler 가 Compile 시점에 해결할 수 있는 Binding 은 아래의 명칭으로 부른다.
- Static binding
- 초기 Binding
모든 static, private, final method 의 binding 은 Compile 시점에서 이뤄지게 진다.
// Java Program to Illustrate Static Binding
// Main class
class NewClass {
// Static nested inner class
// Class 1
public static class superclass {
// Method of inner class
static void print() {
// Print statement
System.out.println( "print() in superclass is called");
}
}
// Static nested inner class
// Class 2
public static class subclass extends superclass {
// Method of inner class
static void print() {
// print statement
System.out.println( "print() in subclass is called");
}
}
// Method of main class
// Main driver method
public static void main(String[] args) {
// Creating objects of static inner classes
// inside main() method
superclass A = new superclass();
superclass B = new subclass();
// Calling method over above objects
A.print();
B.print();
}
}예시를 살펴보고자 Reference 의 페이지에서 예시 코드를 가져왔다. A 는 부모 Class 의 Instance 를 생성하고 있으며, B 는 자식 Class 의 Instance 를 생성하고 있다.
이때, 출력의 결과는 2개 다 superclass 의 print 메서드를 호출하고 있는데, 이는 print 메서드가 static 으로 선언되어 있는 method 이기 때문이다. static 멤버 혹은 메서드는 Compile 시점에 해당 Class 의 Memory 공간 ( Heap 영역 ) 에 저장된다.
superclass B = new subclass();
자식 Class 의 Instance 라 하여도, 참조 변수는 부모 Class 의 Instance 이므로, print 메서드를 호출했을 시, 부모 Class 의 static method 로 호출하는 것이다.
Dynamic Binding
동적 바인딩에서는 Compiler 가 호출할 메서드를 정하지 않는다. → Compiler 에게 권한이 없음!
// Java Program to Illustrate Dynamic Binding
// Main class
public class GFG {
// Static nested inner class
// Class 1
public static class superclass {
// Method of inner class 1
void print(){
// Print statement
System.out.println( "print in superclass is called");
}
}
// Static nested inner class
// Class 2
public static class subclass extends superclass {
// Method of inner class 2
@Override
void print() {
// Print statement
System.out.println( "print in subclass is called");
}
}
// Method inside main class
public static void main(String[] args) {
// Creating object of inner class 1
// with reference to constructor of super class
superclass A = new superclass();
// Creating object of inner class 1
// with reference to constructor of sub class
superclass B = new subclass();
// Calling print() method over above objects
A.print();
B.print();
}
}Dynamic Binding 은 Override 를 예로 들면 이해하기 편하다. 위의 예제의 출력결과는 아래와 같다.
A 같은 경우, superclass 의 print 메서드를 B 같은 경우, subclass 의 print 메서드를 출력한다.
왜 다를까? 간단하게 대답하면 @Override 어노테이션으로 본래의 메서드를 자식 Class 에 맞게 변형했기 때문이라고 말할 수 있다. 그리고 static method 가 아니기 때문에, Class 의 정보가 아닌 Instance 의 정보로 다뤄지고 있기도 하다.
Compile 하는 과정에서 Compiler 는 객체의 Type 이 아닌 참조 변수만 사용하기 때문에 어떤 것을 Print 해야될지 모르는 상황이 온다. 이 상황이 Runtime 까지 지속되며, Runtime 과정에서 객체의 Type 에 따라 Method 가 호출되기 때문에 자식 Class 의 Method 가 호출된 것이다!
Static Binding vs. Dynamic Binding
여기서부터 필자의 생각이 조금 녹아들어있는 부분인데, 성능 면에서는 static binding 이 좋다고 생각이 든다. 따로 Overhead 도 생기지 않기 때문이기도 함..
Compiler 도 이러한 메서드가 Override 될 수 없고, 항상 Local Class 의 객체에 의해서 접근한다는 사실을 알고 있으면, Class 객체의 정보를 파악하는데에 아무런 문제가 없기 때문이다! 하지만 이 말이 모든 상황에서 static 을 붙이고, 하라는 것은 아니다.
동적 Binding 을 사용함으로써, 불특정 객체가 들어올 지 모르는 상황이 있을 수 있는데, 해당 객체에 대한 정보를 Runtime 에서 Binding 할 수 있다는 것 자체가 유지보수 측면에서 이득이라고 생각이 들기 때문이다.
느낀 점
Java 의 메모리 구조를 정확히 파악을 못하여, 오늘 설명하는 부분에서 메모리 부분을 내가 그려서 보여줄 수 있으면 더 좋은 포스팅이 되지 않았을까 싶어, 지금부터 메모리 부분 공부하러 가려고 한다.. 주말인데, 날씨도 좋고, 그냥 나가서 코딩할까하다가 에어컨 바람이 너무 시원해서 집에서 포스팅을 끝마친다.