我包含的代码的输出非常难看,但它只是一个用于理解Java中不同功能的代码。质疑的行在代码的下半部分标有注释。
class CsTorta extends Torta{
public CsTorta retegez(CsTorta a){
....
}
public CsTorta retegez(Torta a){
System.out.println("This method"); //<-----it calls this one and not the one above
....
}
}
public class NewClass {
public static void main(String[] args) {
Torta tt=new Torta(5);
Torta tcs=new CsTorta(3);
CsTorta cs=new CsTorta(4);
System.out.println("");
System.out.println(tcs.retegez(tcs)); //The line in question uses the cstorta retegez method (marked with "This method")
}
}
虽然tcs在编码时的类型是引用类型,但在运行时,当我调用tcs.retegez方法时,它识别出它的cstorta类型,但是相同tcs的参数仍然是引用类型(这就是它使用的原因) cstorta标记方法)。
我的问题是:我的结论是否正确:如果程序调用方法,程序只检查对象的“真实”类型,如果不调用,则使用引用类型?
答案 0 :(得分:1)
这非常正确。这里需要的是理解重载和重写之间的区别。
当你有一个声明一个实例方法的类和一个声明相同方法的子类(同名,相同的参数 - 结果类型通常相同但可以是子类)时,会发生覆盖。有多种方法可供选择,但确切的方法是在运行时确定的。
public class A {
public void method1(String s1, int s2) { ... }
}
public class B extends A {
@Override
public void method1(String s1, int s2) { ... }
}
A object = new B();
object.method1("xxx",2);
关于运行method1
的决定直到运行时才会生效。 object
的真实类型为B
,因此method1
中声明的B
会被调用。
重载是指同时存在两个名称相同但参数不同的方法。通过不同的参数,我的意思是参数的数量不同,或者参数的数量是相同的,但类型是不同的。也就是说,他们有不同的签名。在这种情况下,决定调用哪个方法是在编译时。 (您可以遇到覆盖和重载都发生的情况。选择哪个参数签名的决定是在编译时进行的;但如果有多个覆盖方法具有相同的签名,则在运行时选择这些方法。 )
要记住的关键是,如果在编译时做出决定,编译器将不知道&#34; real&#34;对象的类型是。它只知道你是如何宣布它的。因此:
public CsTorta retegez(CsTorta a){ // Number 1
....
}
public CsTorta retegez(Torta a){ // Number 2
System.out.println("This method"); //<-----it calls this one and not the one above
....
}
这些重载方法。
您的代码如下:
Torta tcs = // the compiler doesn't care
System.out.println(tcs.retegez(tcs));
编译器必须决定是调用Number 1还是Number 2.所有编译器都知道参数是Torta
。实际值可以是Torta
,CsTorta
或任何其他类的对象。或者它可以是null
(好吧,如果它为空,则无法调用tcs.retegez
,但如果您说tcs.retegez(tcs2)
,那么tcs2
就可以是null。)编译器不知道,也不关心。它只知道它被声明为Torta
,因此它选择带有Torta
参数的重载方法。
(进一步澄清:编译器将选择最深的子类。例如:)
class AnotherTorta extends Torta { ... }
class YetAnotherTorta extends CsTorta { ... }
AnotherTorta t3 = // whatever
YetAnotherTorta t4 = // whatever
tcs.retegez(t3);
// since AnotherTorta can't be cast to CsTorta, it chooses the Torta parameter
tcs.retegez(t4);
// here, t4 can be cast to either a Torta or CsTorta parameter, so it chooses the subclass, CsTorta