gpt4 book ai didi

java - 覆盖和重载的方法

转载 作者:行者123 更新时间:2023-11-29 04:08:40 25 4
gpt4 key购买 nike

“转换影响编译时重载方法的选择但不影响重写方法”是什么意思?

我阅读了以下关于“覆盖方法和动态绑定(bind)”( https://www.oreilly.com/library/view/learning-java-4th/9781449372477/ch06s01.html ) 的文章,但我无法理解最后一段

“在上一节中,我们提到重载方法是在编译时由编译器选择的。另一方面,重写方法是在运行时动态选择的。即使我们创建子类的实例,我们的代码也永远不会之前看到(可能是通过网络加载的新类),它包含的任何重写方法都在运行时定位和使用,替换我们上次编译代码时存在的方法。

相比之下,如果我们创建一个新类来实现一个额外的、更具体的重载方法,并用它替换类路径中已编译的类,我们的代码将继续使用它最初发现的实现。这种情况会一直存在,直到我们重新编译我们的代码和新类。这样做的另一个影响是强制转换(即明确告诉编译器将对象视为其可分配类型之一)会影响编译时重载方法的选择,但不会影响重写方法。”

我无法理解“Casting”行:“这的另一个影响是,强制转换(即明确告诉编译器将对象视为其可分配类型之一)会影响编译时重载方法的选择,但不会被覆盖方法。”

最佳答案

该行指的是

  • overloaded versions of a method are chosen at compile time, based on the compile-time types of the arguments that you are passing; whereas
  • overridden methods are chosen at run time, based on the classes of the objects on which you call each method.

要理解这种区别,请考虑您同时具有覆盖和重载的情况,如下所示。

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 类的方法。这发生在运行时,基于调用该方法的对象的,而不是您调用该方法的变量的类型。 p>

所以在这种情况下,重要的是名为 cujo 的对象的类。在这个例子中,cujo 是一只 Rottweiler,因此我们得到了该方法的重写版本 - 在 Rottweiler 类中定义的那个。

这个例子会打印出I'm going to eat you

To summarise:

  • The overload is chosen at compile time based on the parameter type.
  • The override is chosen at run time based on the object class.

现在,可以使用转换来更改编译器对重载的选择。 不可能使用转换来更改覆盖的运行时选择。所以,我们可以写

cujo.barkAt((Postman) pat);

这一次,传递给方法的参数是一个Postman类型的表达式。编译器相应地选择一个重载,这将打印 I'm going to rip you apart.

关于java - 覆盖和重载的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56535768/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com