运行时

时间:2017-07-01 23:37:02

标签: java runtime reference-type

我包含的代码的输出非常难看,但它只是一个用于理解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标记方法)。

我的问题是:我的结论是否正确:如果程序调用方法,程序只检查对象的“真实”类型,如果不调用,则使用引用类型?

1 个答案:

答案 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。实际值可以是TortaCsTorta或任何其他类的对象。或者它可以是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