>  기사  >  Java  >  Java 정적 바인딩 및 동적 바인딩 예제 코드에 대한 자세한 설명

Java 정적 바인딩 및 동적 바인딩 예제 코드에 대한 자세한 설명

伊谢尔伦
伊谢尔伦원래의
2017-07-17 16:11:071627검색

Java 정적 바인딩 및 동적 바인딩

프로그램 바인딩의 개념:

바인딩은 메서드가 위치한 클래스(메서드 본문)와 메서드 호출을 연결하는 것을 말합니다. Java의 경우 바인딩은 정적 바인딩과 동적 바인딩으로 구분됩니다. 컴파일 과정에서 이 메서드가 어떤 클래스에 있는지는 이미 알려져 있으며 이때 컴파일러나 다른 링커에 의해 구현됩니다. 예: C.

Java의 경우 프로그램 컴파일 중 바인딩으로 간단히 이해할 수 있습니다. 여기에는 특별 참고 사항이 있습니다. Java의 최종, 정적, 비공개 및 생성자 메서드만 미리 바인딩되어 있습니다.

동적 바인딩:


후기 바인딩 : 런타임 시 특정 개체의 유형을 기반으로 바인딩합니다.

언어가 런타임에 바인딩을 구현하는 경우 런타임 중에 개체 유형을 결정하고 적절한 메서드를 각각 호출하는 메커니즘도 제공해야 합니다. 즉, 컴파일러는 현재 객체의 유형을 아직 알지 못하지만 메서드 호출 메커니즘은 자체적으로 조사하여 올바른 메서드 본문을 찾을 수 있습니다. 언어마다 후기 바인딩을 다르게 구현합니다. 그러나 우리는 적어도 이렇게 생각할 수 있습니다. 그들은 모두 객체에 특별한 유형의 정보를 배치해야 합니다.

동적 바인딩 프로세스:


가상 머신은 객체의 실제 유형의 메소드 테이블을 추출합니다.

가상 머신은 메소드 서명을 검색합니다. 방법.
  1. 최종 메소드, 정적 메소드, 프라이빗 메소드, 생성자 메소드가 미리 바인딩되어 있다는 점에 대해
  2. 프라이빗 메소드의 경우 우선 상속이 불가능하기 때문에 호출할 방법이 없습니다. 하위 클래스의 객체이며 이 클래스 자체의 객체를 통해서만 호출할 수 있습니다. 따라서 private 메소드는 이 메소드를 정의하는 클래스에 바인딩되어 있다고 할 수 있습니다.

  3. 최종 메소드는 상속받을 수 있지만, 하위 클래스 객체를 호출할 수는 있지만 상위 클래스에 정의된 최종 메소드를 호출하는 방법을 알 수 있습니다. 이는 첫 번째로 메소드가 재정의되는 것을 방지하고 두 번째로 Java에서 동적 바인딩을 효과적으로 끄는 최종 유형입니다.

    생성자는 상속될 수 없습니다(인터넷에서는 서브클래스가 부모 클래스의 매개변수 없는 생성자를 무조건 상속받아 자신의 생성자로 사용한다는 말도 있지만, 개인적으로는 서브클래스가 super() 호출을 사용한다는 것을 알기 때문에 이 진술은 적절하지 않다고 생각합니다. 부모 클래스의 초기화를 완료하기 위해 부모 클래스의 매개변수 없는 생성자를 사용하면 부모 클래스에서 상속받은 메서드를 사용할 때 이 작업을 수행할 필요가 없으므로 하위 클래스가 부모 클래스의 생성자를 상속한다고 말해서는 안 됩니다. 또한 이 생성자가 어떤 클래스에 속하는지도 알고 있습니다.

정적 방식의 경우 구체적인 원리를 명확하게 설명할 수 없습니다. 하지만 인터넷 정보와 제가 직접 실험한 내용을 토대로 정적 메서드는 하위 클래스에서 상속할 수 있지만 하위 클래스에서 재정의(overridden)할 수는 없지만 하위 클래스에서 숨길 수는 있다는 결론을 내릴 수 있습니다. (즉, 상위 클래스에 정적 메소드가 있고 하위 클래스에 해당 메소드가 없는 경우 하위 클래스 객체가 이 메소드를 호출하면 상위 클래스의 메소드가 사용됩니다. 그리고 해당 메소드가 subclass 동일한 메소드는 하위 클래스에 정의된 메소드를 호출합니다. 유일한 차이점은 하위 클래스 객체가 상위 클래스 객체로 변환될 때 해당 객체는 하위 클래스에 정의되어 있는지 여부에 관계없이 상위 클래스의 정적 메소드를 사용한다는 것입니다. 따라서 정적 메서드는 숨길 수는 있지만 재정의할 수는 없다고 합니다. 이는 하위 클래스가 상위 클래스의 멤버 변수를 숨기는 것과 같습니다. 상위 클래스 객체는 숨겨질 수 있습니다. 상위 클래스의 숨겨진 변수와 메서드에는 액세스할 수 있지만 상위 클래스의 재정의된 메서드에는 액세스할 수 없습니다.)


위에서 우리는 메서드가 상속될 수 없거나 불가능하다는 결론을 내릴 수 있습니다. 상속 후에 재정의되는 경우 이 메서드는 정적 바인딩이 사용됩니다.


Java의 컴파일 및 실행



Java의 컴파일 과정은 Java 소스 파일을 바이트코드(jvm 실행 코드, 즉 .class 파일)로 컴파일하는 과정입니다. 이 과정에서 Java는 메모리를 처리하지 않습니다. , 이 프로세스 중에 컴파일러는 구문을 분석하고 구문이 올바르지 않으면 오류를 보고합니다.


Java의 실행 프로세스는 jvm(Java Virtual Machine)이 바이트코드 파일을 로드하고 이를 해석하여 실행하는 것을 의미합니다. 이 과정에서 실제로 메모리 레이아웃이 생성되고 자바 프로그램이 실행된다.
Java 바이트코드를 실행하는 방법에는 두 가지가 있습니다. (1) JIT(Just-In-Time) 컴파일 방법: 인터프리터는 먼저 바이트를 기계어 코드로 컴파일한 다음 기계어 코드를 실행합니다. (2) 해석 실행 방법: 인터프리터가 각 해석을 전달합니다. 그리고 작은 코드 조각을 실행하여 Java 바이트코드 프로그램의 모든 작업을 완료합니다. (여기서 우리는 Java 프로그램이 실행 중에 실제로 두 번 변환되는 것을 볼 수 있습니다. 첫 번째는 바이트 코드로, 그 다음에는 기계 코드로 변환됩니다. 이것이 Java가 한 번 컴파일되어 어디에서나 실행될 수 있는 이유입니다. 다른 플랫폼에서 해당 Java 가상 머신을 설치하면 동일합니다. 바이트코드는 다른 플랫폼에서 기계어 코드로 변환되어 다른 플랫폼에서 실행될 수 있습니다)

앞서 언급했듯이 Java의 메소드에 대해서는 final을 제외하고 사전 바인딩된 정적, 비공개 및 생성자 메소드를 제외하고 다른 모든 메소드는 메소드는 동적으로 바인딩됩니다.
동적 바인딩은 일반적으로 상위 클래스와 하위 클래스의 변환 선언에서 발생합니다.

예: Parent p = new Children();

구체적인 프로세스 세부 정보는 다음과 같습니다.

1: 컴파일러 확인 선언된 유형 그리고 객체의 메소드 이름입니다.

x.f(args) 메소드를 호출하고 x가 클래스 C의 객체로 선언되었다고 가정하면 컴파일러는 클래스 C 메소드의 f라는 이름의 모든 메소드와 클래스 C 메소드의 슈퍼 클래스에서 상속된 f를 열거합니다.

2: 다음으로 컴파일러는 메서드 호출에 제공된 매개 변수 유형을 확인합니다.

f라는 모든 메소드 중에 호출에서 제공하는 매개변수 유형과 가장 잘 일치하는 매개변수 유형이 있는 경우 이 프로세스를 "과부하 해결"이라고 합니다.

3: 프로그램이 실행 중이고 동적 바인딩을 사용하여 메서드가 호출되면 가상 머신은 x가 가리키는 개체의 실제 유형과 일치하는 메서드 버전을 호출해야 합니다.

실제 유형이 D(C의 하위 클래스)라고 가정합니다. 클래스 D가 f(String)를 정의하면 이 메서드가 호출됩니다. 그렇지 않으면 D의 슈퍼 클래스에서 메서드 f(String)가 검색됩니다. 곧.
JAVA 가상 머신이 클래스 메소드(정적 메소드)를 호출할 때 객체 참조 유형(일반적으로 컴파일 타임에 알려짐)을 기반으로 호출할 메소드를 선택합니다. 반대로 가상 머신이 인스턴스 메소드를 호출할 때 객체의 실제 유형(런타임에만 알 수 있음)을 기반으로 호출할 메소드를 선택합니다. 이것이 다형성의 일종인 동적 바인딩입니다. . 동적 바인딩은 실제 비즈니스 문제를 해결하는 데 뛰어난 유연성을 제공하며 매우 아름다운 메커니즘입니다.

메서드와 달리 Java 클래스에서 멤버 변수(인스턴스 변수 및 클래스 변수)를 처리할 때 런타임 바인딩을 사용하지 않고 일반적인 의미에서 정적 바인딩을 사용합니다. 따라서 상향 변환의 경우 객체의 메서드는 하위 클래스를 찾을 수 있지만 객체의 속성(멤버 변수)은 여전히 ​​상위 클래스의 속성입니다(하위 클래스는 상위 클래스의 멤버 변수를 숨깁니다).


public class Father { 
  protected String name = "父亲属性"; 
}   
public class Son extends Father { 
  protected String name = "儿子属性"; 
  
  public static void main(String[] args) { 
    Father sample = new Son(); 
    System.out.println("调用的属性:" + sample.name); 
  } 
}

결론적으로 호출된 멤버는 아버지의 속성입니다.

이 결과는 하위 클래스의 객체(상위 클래스의 참조 핸들)가 상위 클래스의 멤버 변수를 호출한다는 것을 보여줍니다. 따라서 런타임(동적) 바인딩의 범위는 개체의 메서드뿐이라는 점을 분명히 해야 합니다.

이제 서브클래스의 멤버변수 이름을 호출하려고 하는데 어떻게 해야 하나요? 가장 간단한 방법은 멤버 변수를 getter 메서드로 캡슐화하는 것입니다.
코드는 다음과 같습니다.


public class Father { 
  protected String name = "父亲属性"; 
  public String getName() { 
    return name; 
  } 
}   
public class Son extends Father { 
  protected String name = "儿子属性"; 
  public String getName() { 
    return name; 
  } 
  public static void main(String[] args) { 
    Father sample = new Son(); 
    System.out.println("调用的属性:" + sample.getName()); 
  } 
}

결과: 아들의 속성은 속성에 대한 정적 바인딩 방법 때문에

Java라고 합니다. 이는 정적 바인딩이 런타임이 아닌 컴파일 타임에 프로그램에서 오류를 찾을 수 있게 해주기 때문에 많은 이점이 있습니다. 이렇게 하면 프로그램의 실행 효율성이 향상됩니다!

위 내용은 Java 정적 바인딩 및 동적 바인딩 예제 코드에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.