Java的静态和动态绑定
作者:baeldung
译者:Emma
1 简介
多态允许对象采用多种形式-当一个方法表现出多态性时,编译器必须将方法的名称映射到最终实现。
如果它在编译时映射,则它是静态或早期绑定。
如果它在运行时被解析,则称为动态或后期绑定。
2 通过代码理解
当子类继承父类时,它可以重新实现它定义的方法。这称为方法重写。
例如,让我们创建一个超类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;
}
}
}
和子类Dog
public class Dog extends Animal {
static Logger logger = LoggerFactory.getLogger(Dog.class);
@Override
public void makeNoise() {
logger.info("woof woof!");
}
}
在重载方法(如Animal类的makeNoise())时,编译器将在编译时解析方法及其代码。这是静态绑定的一个例子。
但是,如果我们分配Dog类型对象指向Animal类型的引用,编译器将在运行时解析函数代码映射。这是动态绑定。
要了解这是如何工作的,让我们编写一个小代码片段来调用这个类及其方法:
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!
现在我们创建一个类:
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");
}
}
将下面这一行添加到主类:
AnimalActivity.eat(dogAnimal);
结果将是:
com.baeldung.binding.AnimalActivity - Animal is eating
此示例显示静态函数进行静态绑定。
原因是子类不能覆盖静态方法。 如果子类实现了相同的方法,它将隐藏超类的方法。 同样,如果方法是final或private,则JVM将执行静态绑定。
静态绑定方法与特定对象无关,而是在Type(Java中的类)上调用。这种方法的执行稍微快一些。
默认情况下,任何其他方法都自动成为Java中的虚方法。 JVM在运行时解析这些方法,这是动态绑定。
确切的实现取决于JVM,但它需要采取类似于C ++的方法,即JVM查找虚拟表以决定调用该方法的对象。
3 结束语
绑定是实现多态性的语言不可或缺的一部分,理解静态和动态绑定的含义很重要,这能确保我们的应用程序按照我们希望的方式运行。
但是,通过这种理解,我们能够有效地使用类继承以及方法重载。