Static and Dynamic Binding in Java – Java中的静态和动态绑定

最后修改: 2018年 8月 15日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

Polymorphism allows an object to take multiple forms – when a method exhibits polymorphism, the compiler has to map the name of the method to the final implementation.

多态性允许一个对象采取多种形式 – 当一个方法表现出多态性时,编译器必须将该方法的名称映射到最终的实现。

If it’s mapped at compile time, it’s a static or early binding.

如果它在编译时被映射,那么它就是一个静态或早期的绑定。

If it’s resolved at runtime, it’s known as dynamic or late binding.

如果它是在运行时解决的,那么它就被称为动态或晚期绑定。

2. Understanding Through a Code

2.通过一个代码来理解

When a subclass extends a superclass, it can re-implement methods defined in by it. This is called a method overriding.

当一个子类扩展一个超类时,它可以重新实现超类中定义的方法。这被称为方法覆盖。

For example, let’s create a superclass Animal:

例如,让我们创建一个超类Animal:

public class Animal {

    static Logger logger = LoggerFactory.getLogger(Animal.class);

    public void makeNoise() {
        logger.info("generic animal noise");
    }

    public void makeNoise(Integer repetitions) {
        while(repetitions != 0) {
            logger.info("generic animal noise countdown " + repetitions);
            repetitions -= 1;
        }
    }
}

And a subclass Dog:

还有一个子类Dog

public class Dog extends Animal {

    static Logger logger = LoggerFactory.getLogger(Dog.class);
    
    @Override
    public void makeNoise() {
        logger.info("woof woof!");
    }

}

On overloading a method, like the makeNoise() of Animal class, the compiler will resolve the method and its code at compile time. This is an example of static binding.

在重载一个方法时,比如Animal类的makeNoise(),编译器将在编译时解析该方法及其代码。这是一个静态绑定的例子。

However, if we assign an object of type Dog to a reference of type Animal, the compiler will resolve the function-code mapping at runtime. This is dynamic binding.

然而,如果我们将一个Dog类型的对象分配给Animal类型的引用,编译器将在运行时解决函数-代码映射。这就是动态绑定。

To understand how this work, let’s write a small code snippet to call the classes and its methods:

为了理解这个工作,让我们写一个小的代码段来调用这些类和它的方法。

Animal animal = new Animal();

// calling methods of animal object
animal.makeNoise();
animal.makeNoise(3);

// assigning a dog object to reference of type Animal
Animal dogAnimal = new Dog();

dogAnimal.makeNoise();

The output of the above code will be:
com.baeldung.binding.Animal - generic animal noise 
com.baeldung.binding.Animal - generic animal noise countdown 3
com.baeldung.binding.Animal - generic animal noise countdown 2
com.baeldung.binding.Animal - generic animal noise countdown 1
com.baeldung.binding.Dog - woof woof!

Now, let’s create a class:

现在,让我们创建一个类。

class AnimalActivity {

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

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

Let us add these the line to the main class:

让我们在主类中加入这一行。

AnimalActivity.eat(dogAnimal);

The output would be:

输出将是。

com.baeldung.binding.AnimalActivity - Animal is eating

This example shows that a static function undergoes static binding.

这个例子显示了一个静态函数经历了静态绑定

The reason is that subclasses cannot override static methods. If the subclass implemented the same method, it would hide the method of the superclass. Similarly, if a method is final or private, the JVM will do a static binding.

原因是,子类不能覆盖静态方法。如果子类实现了相同的方法,它将隐藏超类的方法。类似地,如果一个方法是最终的或私有的,JVM将进行静态绑定。

A static bound method isn’t associated with a particular object but rather is called on Type (class in Java). Execution of such a method is marginally faster.

静态绑定方法并不与特定对象相关联,而是在Type(Java中的类)上调用。执行这样的方法会稍微快一点。

Any other method is automatically a virtual method in Java by default. The JVM resolves such methods at runtime and this is dynamic binding.

任何其他的方法在Java中默认为自动的虚拟方法。JVM会在运行时解析这些方法,这就是动态绑定。

The exact implementation depends on the JVM, but it would take a C++ like approach, where the JVM looks up the virtual table to decide on which object the method would be called.

具体的实现取决于JVM,但它会采取类似于C++的方法,即JVM通过查找虚拟表来决定在哪个对象上调用该方法。

3. Conclusion

3.总结

Binding is an integral part of a language that implements polymorphism, it’s important to understand the implications of both static and dynamic binding to be sure that our applications are behaving as we want them to.

绑定是实现多态性的语言不可分割的一部分,了解静态和动态绑定的含义很重要,以确保我们的应用程序的行为符合我们的要求。

With that understanding, however, we are able to effectively use class inheritance as well as method overloading.

然而,有了这种理解,我们就能够有效地使用类的继承以及方法重载。

As always, the code is available over on GitHub.

像往常一样,代码可在GitHub上获得