바인딩은 메서드 호출을 해당 클래스와 연결하는 것을 의미합니다.
바인딩은 정적 바인딩과 동적 바인딩으로 나눌 수 있습니다.
정적 바인딩과 동적 바인딩을 분석하기 전에 알아야 할 몇 가지 개념:
컴파일 기간: 컴파일 프로세스는 Java 소스를 변환하는 것입니다. 파일을 바이트코드(.class 파일, JVM 실행 코드)로 컴파일하는 과정입니다. 이 과정에서 Java는 메모리를 처리하지 않습니다. 이 과정에서 컴파일러는 구문 분석을 수행합니다. 보고되었습니다.
실행 기간: 실행 프로세스는 JVM(Java Virtual Machine)이 바이트코드 파일을 로드하고 이를 해석하여 실행하는 것을 의미합니다. 메모리 Java 프로그램을 실행합니다.
Java에서 메소드 호출 과정은 다음과 같습니다.
Editor 해당 객체의 선언된 타입과 메소드 이름을 확인합니다. 메서드 오버로드로 인해 호출될 수 있는 모든 후보 메서드를 가져옵니다. 예를 들어, 메소드 1은 print(String str)이고, 메소드 2는 print(int)입니다.
컴파일러는 호출 메서드의 입력 매개변수 유형을 확인합니다. 후보 방법 중에서 일치 방법을 선택합니다. 예를 들어 입력 매개변수가 "hello"인 경우 print(String str)을 선택합니다.
메서드가 private, static, final 또는 생성자인 경우 컴파일러는 호출할 메서드를 결정할 수 있습니다. 이것은 정적 바인딩입니다.
그렇지 않은 경우 런타임(동적) 바인딩을 사용해야 합니다.
정적 바인딩, 초기 바인딩 및 컴파일 타임 바인딩이라고도 합니다. 컴파일 타임에 바인딩을 나타냅니다. 즉, 프로그램이 실행되기 전에 메서드가 바인딩되었음을 나타냅니다.
final, static 및 private으로 수정된 메서드, 멤버 변수 및 생성자만 정적으로 바인딩됩니다.
类型 | 解释 |
---|---|
final | 被其修饰的方法可以被继承,但不能被重写;子类对象可以调用,但是调用的是父类中定义的那个方法;间接表明将方法声明为 final 可以避免重写,关闭动态绑定。 |
private | 被其修饰地方法隐式地包含了 final 关键字。由于它对外是不可见的,所以不能被继承,重写;只能通过类自身的对象来调用,因此在方法运行之前就可以明确对象。 |
static | 静态方法是依赖于类而依赖于对象的。它可以被子类继承(实质是被子类隐藏),但是不能被子类重写。当子类对象向上转型为父类对象时,不论子类中有没有定义这个静态方法,该对象都会使用父类中的静态方法。因此这里说静态方法可以被隐藏。 |
成员变量 | 默认 Java 对属性采用静态绑定,这样在编译期就能发现程序错误,能够提供效率。 |
构造方法 | 构造方法不能被继承的,子类继承父类时默认要先调用父类的构造方法(无论显示或隐式)。因此在程序运行之前就可以知道构造方法术语哪个对象。 |
다음 예를 살펴보세요.
// 父类class Parent{ // 变量 String name="Parent"; // 静态方法 static void print(){ System.out.println("Parent print"); } // 私有方法 private void say(){ System.out.println("Parent say"); } // 终态方法 final void look(){ System.out.println("Parent look"); } }// 子类class Son extends Parent{ String name ="Son"; static void print(){ System.out.println("Son print"); } // 编译错误,无法重写父类的 final方法 final void look(){}; }public class Test{ public static void main(String[] args) { // 发生向上转型 Parent p = new Son(); // 输出 Parent System.out.println(p.name); // 输出 Parent print p.print(); // 编译错误,对外不可见 p.say(); } }
동적 바인딩은 런타임 바인딩이라고도 하며 런타임 시 특정 개체의 유형에 따라 바인딩하는 것을 의미합니다.
동적 바인딩 프로세스:
가상 머신은 객체의 실제 유형의 메소드 테이블을 추출합니다.
가상 기계 검색 메소드 서명
이 메소드를 호출합니다.
예를 살펴보겠습니다.
class A { int x = 5; } class B extends A { int x = 6; } class Parent { public A getValue() { System.out.print("Parent Method "); return new A(); } } class Son extends Parent { public B getValue() { System.out.print("Son Method "); return new B(); } }public class Test { public static void main(String[] args) { // 向上转型 Parent p = new Son(); // 输出结果:Son Method 5 // 注意:是 5 不是 6 ! System.out.println(p.getValue().x); } }
다음과 같이 출력 분석을 관찰합니다.
p.getValue(), 발생으로 인해 상향 변환이 있으므로 먼저 하위 클래스(Son)에서 메서드를 검색하고, 이때 Son의 메서드를 호출합니다. 이것이 동적 바인딩입니다.
p.getValue( ).x. x는 멤버 변수이므로 여기에서 정적 바인딩이 실행되기 전에 해당 개체(Parent에 속함)가 결정됩니다.
아직도 이해가 되지 않는다면 다른 예를 살펴보겠습니다.
class Parent { String name = "Parent " + this.getClass().getName(); } class Son extends Parent { String name = "Son" + this.getClass().getName(); }public class Test { public static void main(String[] args) { // 向上转型 Parent p = new Son(); // 输出:Parent Son System.out.println(p.name); } }
다음과 같이 출력 분석을 관찰합니다.
p.name : name은 멤버 변수이고 이때 static 바인딩이 발생하므로 Parent의 속성이 호출됩니다.
this.getClass( ): getClass는 이때 상향 변환이 발생하므로 기본 프로그램은 이 메소드도 존재하는 하위 클래스부터 검색합니다. 서브클래스. 따라서 서브클래스의 메소드가 호출되며 이때 동적 바인딩이 발생하게 된다.
위 내용은 07.Java Basics - Static Binding & Dynamic Binding의 내용입니다. 자세한 내용은 PHP 중국어를 참고해주세요. 홈페이지(www.php.cn)!