programing

스태틱과Java에서의 다이내믹바인딩

javaba 2022. 10. 6. 21:23
반응형

스태틱과Java에서의 다이내믹바인딩

현재 클래스 중 하나를 할당하고 있는데, 이 클래스에서 Java 구문을 사용하여 정적 바인딩과 동적 바인딩의 를 제시해야 합니다.

정적 바인딩은 컴파일 시, 동적 바인딩은 런타임에 발생한다는 기본 개념은 이해하지만 구체적으로 어떻게 작동하는지 알 수 없습니다.

다음 예시를 나타내는 스태틱바인딩의 예를 찾았습니다.

public static void callEat(Animal animal) {
    System.out.println("Animal is eating");
}

public static void callEat(Dog dog) {
    System.out.println("Dog is eating");
}

public static void main(String args[])
{
    Animal a = new Dog();
    callEat(a);
}

그리고 이것은 "animal is eating"이라고 인쇄될 것입니다. 이것이 스태틱바인딩이라고 생각되는지는 잘 모르겠습니다.

지금까지 내가 본 정보 중 내가 따라갈 수 있는 방식으로 이것을 설명하는 데 성공한 정보원은 없었다.

Javarevisited 블로그 투고:

스태틱 바인딩과 다이내믹바인딩의 중요한 차이점은 다음과 같습니다.

  1. Java의 정적 바인딩은 컴파일 시간 중에 발생하는 반면 동적 바인딩은 런타임 중에 발생합니다.
  2. private,final ★★★★★★★★★★★★★★★★★」static메서드와 변수는 정적 바인딩을 사용하며 컴파일러에 의해 결합되는 반면 가상 메서드는 런타임 개체에 기반하여 런타임 중에 결합됩니다.
  3. 에서는 " " 가 사용됩니다.Type )class동적 바인딩이 개체를 사용하여 바인딩을 해결하는 동안 바인딩에 대한 정보를 제공합니다.
  4. 오버로드된 메서드는 정적 바인딩을 사용하여 결합되며 오버라이드된 메서드는 런타임에 동적 바인딩을 사용하여 결합됩니다.

다음은 Java의 정적 바인딩과 동적 바인딩을 모두 이해하는 데 도움이 되는 예입니다.

Java에서의 스태틱바인딩 예시

public class StaticBindingTest {  
    public static void main(String args[]) {
        Collection c = new HashSet();
        StaticBindingTest et = new StaticBindingTest();
        et.sort(c);
    }
    //overloaded method takes Collection argument
    public Collection sort(Collection c) {
        System.out.println("Inside Collection sort method");
        return c;
    }
    //another overloaded method which takes HashSet argument which is sub class
    public Collection sort(HashSet hs) {
        System.out.println("Inside HashSet sort method");
        return hs;
    }
}

출력: Inside Collection 정렬 방식

Java에서의 다이내믹바인딩 예시

public class DynamicBindingTest {   
    public static void main(String args[]) {
        Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
        vehicle.start(); //Car's start called because start() is overridden method
    }
}

class Vehicle {
    public void start() {
        System.out.println("Inside start method of Vehicle");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        System.out.println("Inside start method of Car");
    }
}

출력: 자동차의 내부 시동 방법

메서드 콜을 메서드바디에 접속하는 것을 Binding이라고 합니다.Maulik의 말처럼, "스태틱 바인딩은 바인딩에 유형(Java의 클래스) 정보를 사용하는 반면, 동적 바인딩은 바인딩을 해결하기 위해 객체를 사용합니다.이 코드는 다음과 같습니다.

public class Animal {
    void eat() {
        System.out.println("animal is eating...");
    }
}

class Dog extends Animal {

    public static void main(String args[]) {
        Animal a = new Dog();
        a.eat(); // prints >> dog is eating...
    }

    @Override
    void eat() {
        System.out.println("dog is eating...");
    }
}

결과는 나올 것이다: 개가 먹고 있다...사용할 메서드를 찾기 위해 개체 참조를 사용하기 때문입니다.위의 코드를 다음과 같이 변경하면:

class Animal {
    static void eat() {
        System.out.println("animal is eating...");
    }
}

class Dog extends Animal {

    public static void main(String args[]) {

        Animal a = new Dog();
        a.eat(); // prints >> animal is eating...

    }

    static void eat() {
        System.out.println("dog is eating...");
    }
}

동물이 먹고 있는...이는 스태틱 메서드이기 때문에 Type(이 경우 Animal)을 사용하여 호출하는 스태틱 메서드를 해결합니다.정적 방법 외에 개인 방법과 최종 방법은 동일한 방법을 사용합니다.

정적 바인딩과 동적 바인딩이 실제로 어떻게 작동하는지 이해하기 위해?컴파일러 및 JVM에 의해 식별되는 방법.

아래 예를 Mammal는 메서드가 입니다.speak() ★★★★★★★★★★★★★★★★★」Human이 연장되다Mammal 을, 을, 을, 보다 우선합니다.speak(), 메서드로 .speak(String language).

public class OverridingInternalExample {

    private static class Mammal {
        public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
    }

    private static class Human extends Mammal {

        @Override
        public void speak() { System.out.println("Hello"); }

        // Valid overload of speak
        public void speak(String language) {
            if (language.equals("Hindi")) System.out.println("Namaste");
            else System.out.println("Hello");
        }

        @Override
        public String toString() { return "Human Class"; }

    }

    //  Code below contains the output and bytecode of the method calls
    public static void main(String[] args) {
        Mammal anyMammal = new Mammal();
        anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
        // 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

        Mammal humanMammal = new Human();
        humanMammal.speak(); // Output - Hello
        // 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

        Human human = new Human();
        human.speak(); // Output - Hello
        // 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

        human.speak("Hindi"); // Output - Namaste
        // 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
    }
}

의 하려고 할 때.javap -verbose OverridingInternalExample컴파일러가 정수 코드를 모든 메서드 호출과 프로그램 자체에 포함하는 프로그램의 바이트 코드에 할당하는 상수 테이블을 생성하는 것을 알 수 있습니다(모든 메서드 호출 아래의 코멘트 참조).

프로그램 바이트 코드

, 「」의 바이트 코드가 되고 있는 을 알 수 .humanMammal.speak(),human.speak() ★★★★★★★★★★★★★★★★★」human.speak("Hindi")다르다invokevirtual #4,invokevirtual #7,invokevirtual #9컴파일러는 인수 리스트와 클래스 참조에 근거해 그것들을 구별할 수 있기 때문입니다.이 모든 것은 컴파일 시에 정적으로 해결되기 때문에 메서드 오버로드는 스태틱 다형성 또는 스태틱바인딩이라고 불립니다.

, 「」의 .anyMammal.speak() ★★★★★★★★★★★★★★★★★」humanMammal.speak()동일)invokevirtual #4 두 메서드는 파파러 ) ) on on on on on on on on on on on ) ) ) ) ) ) ) )로 호출되기 때문입니다.Mammal★★★★★★ 。

두 메서드 호출의 바이트 코드가 동일한 경우 JVM은 어떤 메서드를 호출해야 하는지 어떻게 알 수 있을까요?

자체에 있고, 은 '나'입니다.invokevirtualJVM을 사용합니다.invokevirtualC++는 Java를 사용합니다.C++에서는 다른 클래스의 메서드를 덮어쓰려면 가상 메서드로 선언해야 합니다.단, Java에서는 자녀 클래스의 모든 메서드(프라이빗 메서드, 최종 메서드 및 스태틱 메서드 제외)를 덮어쓸 수 있기 때문에 기본적으로는 모든 메서드가 가상입니다.

Java에서는 모든 참조 변수가 숨겨진 포인터를 2개 보유합니다.

  1. 객체의 메서드를 다시 유지하는 테이블로의 포인터 및 Class 객체에 대한 포인터입니다(예: [speak(), speak(String) Class 객체).
  2. 해당 개체의 데이터(예: 인스턴스 변수 값)에 대해 힙에 할당된 메모리에 대한 포인터입니다.

따라서 모든 개체 참조는 해당 개체의 모든 메서드 참조를 포함하는 테이블에 대한 참조를 간접적으로 유지합니다.Java는 이 개념을 C++에서 차용하여 이 테이블을 가상 테이블(vtable)이라고 부릅니다.

vtable은 어레이 인덱스에서 가상 메서드 이름과 참조를 유지하는 어레이와 같은 구조입니다.JVM은 클래스를 메모리에 로드할 때 클래스당 하나의 vtable만 생성합니다.

이 JVM과 invokevirtual명령 집합은 메서드 참조에 대해 해당 클래스의 vtable을 확인하고 참조가 아닌 객체에서 메서드인 특정 메서드를 호출합니다.

이 모든 것은 실행 시에만 해결되며 실행 시 JVM은 어떤 메서드를 호출해야 하는지 알게 되기 때문에 메서드 오버라이딩을 동적 다형성 또는 단순 다형성 또는 동적 바인딩이라고 합니다.

자세한 내용은 내 기사 "JVM이 내부적으로 메서드 오버로드오버라이드 처리하는 방법"을 참조하십시오.

는 "이 "a"인 .Animal; ; ; ; ; ;의그 때문에, 스태틱바인딩(메서드 오버로드)이라고 불립니다., 이 은 ,, 이, 이, 이, 이, but을 호출합니다.Dog바인딩의 .다이내믹 바인딩의 예를 다음에 나타냅니다.

public class DynamicBindingTest {

    public static void main(String args[]) {
        Animal a= new Dog(); //here Type is Animal but object will be Dog
        a.eat();       //Dog's eat called because eat() is overridden method
    }
}

class Animal {

    public void eat() {
        System.out.println("Inside eat method of Animal");
    }
}

class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("Inside eat method of Dog");
    }
}

출력: 개의 내부 식사 방법

컴파일러를 설계할 때 스태틱바인딩과 다이내믹바인딩에는 크게 3가지 차이점이 있으며 변수와 프로시저가 런타임 환경으로 전송되는 방법이 있습니다.이러한 차이는 다음과 같습니다.

정적 바인딩:스태틱 바인딩에서는 다음 3가지 문제에 대해 설명합니다.

  • 절차의 정의

  • 명칭 선언(변수 등)

  • 선언 범위

동적 바인딩:다이내믹 바인딩에서 발생하는3가지 문제는 다음과 같습니다.

  • 절차의 활성화

  • 이름의 바인딩

  • 바인딩의 수명

부모 클래스와 자녀 클래스의 정적 메서드를 사용하는 경우:스태틱 바인딩

public class test1 {   
    public static void main(String args[]) {
        parent pc = new child(); 
        pc.start(); 
    }
}

class parent {
    static public void start() {
        System.out.println("Inside start method of parent");
    }
}

class child extends parent {

    static public void start() {
        System.out.println("Inside start method of child");
    }
}

// Output => Inside start method of parent

동적 바인딩:

public class test1 {   
    public static void main(String args[]) {
        parent pc = new child();
        pc.start(); 
    }
}

class parent {
   public void start() {
        System.out.println("Inside start method of parent");
    }
}

class child extends parent {

   public void start() {
        System.out.println("Inside start method of child");
    }
}

// Output => Inside start method of child

여기 있는 모든 답은 맞지만, 저는 부족한 것을 추가하고 싶습니다.스태틱 메서드를 덮어쓸 경우 덮어쓰는 것처럼 보이지만 실제로는 메서드 덮어쓰기가 아닙니다.대신 메서드 숨김이라고 합니다.Java에서는 정적 메서드를 재정의할 수 없습니다.

다음 예시를 참조하십시오.

class Animal {
    static void eat() {
        System.out.println("animal is eating...");
    }
}

class Dog extends Animal {

    public static void main(String args[]) {

        Animal a = new Dog();
        a.eat(); // prints >> animal is eating...

    }

    static void eat() {
        System.out.println("dog is eating...");
    }
}

동적 바인딩에서 메서드는 참조 변수가 보유하고 있는 객체의 유형이 아니라 참조 유형에 따라 호출됩니다. 여기서 스태틱바인딩은 메서드 은닉이 동적 다형이 아니기 때문에 발생합니다.eat() 앞에서 static 키워드를 삭제하고 비static 메서드로 하면 메서드 숨김이 아닌 동적 다형이 나타납니다.

답변을 뒷받침하는 다음 링크를 찾았습니다.https://youtu.be/tNgZpn7AeP0

컴파일 시에 결정되는 객체의 정적 바인딩 타입의 경우, 런타임에 결정되는 객체의 동적 바인딩 타입의 경우.



class Dainamic{

    void run2(){
        System.out.println("dainamic_binding");
    }

}


public class StaticDainamicBinding extends Dainamic {

    void run(){
        System.out.println("static_binding");
    }

    @Override
    void run2() {
        super.run2();
    }

    public static void main(String[] args) {
        StaticDainamicBinding st_vs_dai = new StaticDainamicBinding();
        st_vs_dai.run();
        st_vs_dai.run2();
    }

}

컴파일러는 컴파일 시 바인딩을 알고 있기 때문입니다.예를 들어 인터페이스 상에서 메서드를 호출하면 컴파일러는 알 수 없고 바인딩은 실행 시 해결됩니다.이는 메서드가 호출된 실제 객체가 여러 개 중 하나일 수 있기 때문입니다.따라서 런타임 또는 다이내믹바인딩입니다.

유형을 지정했으므로 호출이 컴파일 시 Animal 클래스에 바인딩됩니다.이 변수를 다른 메서드로 전달하면 실제 클래스가 어떤 것인지(작성했기 때문에) 알 수 없습니다.유일한 단서는 선언된 동물의 유형이다.

언급URL : https://stackoverflow.com/questions/19017258/static-vs-dynamic-binding-in-java

반응형