首先,我觉得Java有时使用运行时绑定并且有时编译时间绑定是非常奇怪的。如果它总是运行时绑定不是更简单吗?无论如何。我的问题如下:
在以下代码中:
public class Animal {
public void eat() {
System.out.println("Generic Animal Eating Generically");
}
}
public class Horse extends Animal {
@override
public void eat() {//overridden eat method
System.out.println("Horse eating hay ");
}
public void eat(String s) {//overloaded eat method
System.out.println("Horse eating " + s);
}
}
问题: 1.在下面的代码中,我知道“哪种方法可以运行?”在编译时决定。太明显了。但是决定它的标准是什么?
Animal a = new Animal();
a.eat();
2.以下代码中的内容。
Animal a = new Horse();//line 1
a.eat();
我知道在这种情况下,方法被覆盖并且发生了运行时绑定。但是编译器跳过编译时绑定的标准是什么?
我的假设:它是否认为数据类型和构造函数调用属于不同的类(在第1行中),并且由于这种差异,它会跳过编译时绑定?
3.在下面的代码中:
Animal a = new Horse();
a.eat("some string");//compile time error
如果我的假设为真,则此代码不应导致编译时错误,因为已跳过编译时绑定。我无法理解为什么它会产生编译时错误。 有人可以澄清吗?
答案 0 :(得分:2)
它几乎总是运行时绑定。即所有的java方法都是虚方法。除了非虚拟的静态方法。
也无法覆盖最终和私有方法。
但是,我们在java中确实有一些编译时类型检查。在以下代码中,您遇到编译错误,因为类Animal
没有eat(String)
方法。
Animal a = new Horse();
a.eat("some string");//compile time error
如果Animal
有eat(String)
方法,则代码会编译。但是,由于运行时绑定,它将执行Horse.eat()
。
在动态类型语言中,如python或javascript,没有这种类型检查。如果该方法在运行时存在,则会调用它。否则会抛出错误。这也称为Duck Typing。
答案 1 :(得分:2)
实例方法调用规则非常简单:
答案 2 :(得分:1)
Java使用实际类在运行时找到所需的方法,但它使用接口来判断实际上是方法在编译时。您的班级动物 隐式还定义了动物界面,在这种情况下,该界面仅包含无参数方法'吃()&#39 ;.它没有定义单参数方法' eat(String)'。类马隐式定义 Horse 接口,该接口使用单参数方法扩展 Animal 接口。
在您的示例(1)和(2)中,无论您实例化哪个实际类,都将分配给实现 Animal 接口的变量。因此,当编译器看到语句' a.eat();'它会检查' a'的界面。实现一种无论证的方法' eat()' - 它做的。在您的示例(3)中,实际的类是马但该变量仍然只实现 Animal 接口; at statement' a.eat(" some string");'它检查是否' a'实施' eat(String)' - 它没有,因此编译错误。