我真的很困惑动态绑定和静态绑定。我读到过,在编译时确定对象的类型称为静态绑定,在运行时确定它称为动态绑定。
下面的代码发生了什么:
静态绑定还是动态绑定?
这说明了什么样的多态性?
class Animal
{
void eat()
{
System.out.println("Animal is eating");
}
}
class Dog extends Animal
{
void eat()
{
System.out.println("Dog is eating");
}
}
public static void main(String args[])
{
Animal a=new Animal();
a.eat();
}
您的示例是动态绑定,因为在运行时确定a
的类型,并调用适当的方法。
现在假设您还有以下两个方法:
public static void callEat(Animal animal) {
System.out.println("Animal is eating");
}
public static void callEat(Dog dog) {
System.out.println("Dog is eating");
}
即使您将main
更改为
public static void main(String args[])
{
Animal a = new Dog();
callEat(a);
}
这将打印Animal is eating
,因为对callEat
的调用使用了静态绑定,编译器只知道a
是Animal
类型。
这实际上取决于重载和重写如果你这样做:
public class Animal{}
public class Dog extends Animal{}
public class AnimalActivity{
public void eat(Animal a){
System.out.println("Animal is eating");
}
public void eat(Dog d){
System.out.println("Dog is eating");
}
}
然后在主类中:
public static void main(String args[])
{
Animal a=new Animal();
Animal d=new Dog();
AnimalActivity aa=new AnimalActivity();
aa.eat(a);
aa.eat(d);
}
两种情况下的结果将是:Animal is eating
但是让我们扭转一下,让我们这样:
public class Animal{
public void eat(){
System.out.println("Animal is eating");
}
}
:
public class Dog extends Animal{
public void eat(){
System.out.println("Dog is eating");
}
}
然后在主类中:
public static void main(String args[]){
Animal d=new Dog();
Animal a=new Animal();
a.eat();
d.eat();
}
现在结果应该是:
Animal is eating
Dog is eating
这是因为重载在编译时绑定了"静态绑定"当在运行时重写绑定时"动态绑定"
您的当前代码将输出Animal is eating
然而,在你的主类中,如果你创建了一个Dog
类型的对象并将其分配给Animal
,那么由于动态绑定,你的输出将是Dog is eating
。
public static void main(String args[])
{
Animal a = new Dog(); // An object of Dog is assigned to Animal
a.eat(); // Dynamically determines which eat() method to call
}
尽管a
被声明为Animal
,但它指向的是Dog
类型的对象。因此,在运行时,确定对象类型并调用适当的eat()
方法。
可以这样理解,method overloading
是静态绑定的,method overriding
是动态绑定的。
对于非静态函数,只要函数是非虚拟的,即final
关键字应用于它和/或函数是private
,就使用静态绑定。final
表示该函数不能更改,private
关键字表示该函数只有类作用域。否则使用动态绑定。
对于静态函数,总是使用静态绑定。如果类型A
被传入,它将运行A
的方法,无论A
引用到哪里。
Case 1:
Animal a =new Animal();
a.eat();
案例2:
Animal a=new Dog();
a.eat();
这里两者都是动态绑定,因为在编译时确定对象的类型,但在运行时基于实例,分配相应eat方法的对象将由JVM动态绑定。
在第一个例子中,动物类eat方法被调用,而在第二个例子中,狗类eat被调用,因为animal对象被分配了一个dog实例。狗的例子也是动物的例子。也就是说,你可以把它理解为"是"关系,狗是一种动物。因此,这里对象的类型在运行时被确定为dog, JVM动态绑定dog类的eat方法。
查看此链接
http://www.javatpoint.com/static-binding-and-dynamic-binding http://www.coderanch.com/t/386124/java/java/Static-Binding-Dynamic-Binding检查这个employee类有抽象的earning()
函数,每个类有不同的toString()
实现
Employee[] employees = new Employee[4];
// initialize array with Employees
employees[0] = new SalariedEmployee();
employees[1] = new HourlyEmployee();
employees[2] = new CommissionEmployee();
employees[3] = new BasePlusCommissionEmployee();
for (Employee currentEmployee : employees){
System.out.println(currentEmployee); // invokes toString
System.out.printf("earned $%,.2f%n", currentEmployee.earnings());
}
所有对toString
和earnings
方法的调用都在execution time
处解析,基于currentEmployee所引用的type of the object
,
此过程称为dynamic binding
或late binding
参考资料:Java™如何编程(早期对象),第十版