“投射会影响编译时重载方法的选择,但不会覆盖重载方法”是什么意思?
我阅读了以下有关“重写的方法和动态绑定”(https://www.oreilly.com/library/view/learning-java-4th/9781449372477/ch06s01.html)的文章,但我听不懂最后一段
“在上一节中,我们提到了重载方法是由编译器在编译时选择的。另一方面,重写方法是在运行时动态选择的。即使我们创建子类的实例,我们的代码也永远不会如前所述(也许是一个通过网络加载的新类),它包含的所有替代方法都可以在运行时找到并使用,从而替换上次编译代码时存在的方法。
相反,如果我们创建一个新的类来实现一个额外的,更特定的,重载的方法,并用它替换我们的类路径中的已编译类,则我们的代码将继续使用其最初发现的实现。这种情况将一直持续到我们将代码与新类一起重新编译。这样做的另一个效果是,强制转换(即,明确地告诉编译器将对象视为其可分配类型之一)在编译时会影响重载方法的选择,但不会覆盖重写的方法。”
我无法理解“ Casting”这一行:“这的另一个影响是强制转换(即,明确地告诉编译器将对象视为其可分配类型之一)在编译时会影响重载方法的选择,但不会被覆盖方法。”
答案 0 :(得分:2)
该行指的是
方法的
- 重载版本是在编译时根据传递的参数的编译时类型选择的;而
- 在运行时根据调用每个方法的对象的类别选择覆盖的方法。
要了解这种区别,请考虑这样一种情况,即您同时具有覆盖和重载。
public class Person {
}
---------------------------------------------------------
public class Postman extends Person {
}
---------------------------------------------------------
public class Dog {
public void barkAt(Person p) {
System.out.println("Woof woof");
}
public void barkAt(Postman p) {
System.out.println("Grrrr");
}
}
---------------------------------------------------------
public class Rottweiler extends Dog {
@Override
public void barkAt(Person p) {
System.out.println("I'm going to eat you.");
}
@Override
public void barkAt(Postman p) {
System.out.println("I'm going to rip you apart.");
}
}
在这种情况下,我们这样调用barkAt
方法之一。
Dog cujo = new Rottweiler();
Person pat = new Postman();
cujo.barkAt(pat);
现在在这种特殊情况下,由编译器选择cujo.barkAt(pat);
调用诸如public void barkAt(Person p)
或public void barkAt(Postman p)
之类的方法。这些方法是彼此的重载。
为此,编译器查看传递给方法的表达式的类型-即变量pat
。变量pat
的类型为Person
,因此编译器选择方法public void barkAt(Person p)
。
编译器不要做的是选择是调用Rottweiler
类还是Dog
类中的方法。发生这种情况是在运行时,基于调用该方法的对象的 class ,而不是基于调用该方法的变量的 type 。>
因此,在这种情况下,重要的是称为cujo
的对象的类。在此示例中,cujo
是Rottweiler
,因此我们获得了该方法的替代版本-在Rottweiler
类中定义的版本。
此示例将打印出I'm going to eat you
。
总结:
- 根据参数 type 在编译时选择重载。
- 根据对象 class 在运行时选择替代。
现在,可以使用强制转换来更改编译器对重载的选择。 不可能使用强制转换来更改覆盖的运行时选择。所以,我们可以写
cujo.barkAt((Postman) pat);
这一次,传递给方法的参数是类型Postman
的表达式。编译器会相应地选择一个重载,这将显示I'm going to rip you apart.
。
答案 1 :(得分:-1)
投射会影响编译时重载方法的选择,但不会覆盖重载方法
重载的方法在编译时可见。但是被覆盖的方法在运行时变得可见。
拇指法则:
Java根据引用变量的内容而不是引用变量的类型来调用重写的方法。
下面的例子是自我解释。希望对您有所帮助。
class Animal {
public void speak() {
System.out.print("Animal sounds/roars.");
}
}
class Human extends Animal {
@Override // Method is overridden
public void speak() {
System.out.print("Humans talking english.");
}
public void speak(String words) { // Method is overloaded.
System.out.print("We have brain. We are intelligent."+words);
}
}
class Earth {
public static void main(String a[]) {
Animal a = new Animal();
a.speak(); // Prints Animal sounds/roars.
Human h = new Human();
h.speak(); // Prints "Humans talking english."
Animal a = h; // Cast to superclass reference variable. However, underlying object is of Human.
a.speak(); // Prints "Humans talking english." because speak() is known by Animal at compile time. During runtime,
// the object contains the human object and hence java calls human overridden method.
a.speak("I want to be human."); // Compile time error as speak(..) is not known by Animal at compile time.
}
}