动态方法分派和运行时多态性错误

Posted

技术标签:

【中文标题】动态方法分派和运行时多态性错误【英文标题】:Dynamic method dispatch and runtime polymorphism error 【发布时间】:2020-04-29 03:54:04 【问题描述】:

我正在尝试理解动态方法调度。

class A 
int i=10;
void callme() 
    System.out.println("Inside A's callme method");
 
class B extends A 
int j=20;
    void callme() 
        System.out.println("Inside B's callme method");
 
class C extends A 
int k=30;
void callme() 
    System.out.println("Inside C's callme method");
 
class  Over_riding_loading
    public static void main(String args[]) 
        A a = new A(); 
        B b = new B(); 
        C c = new C(); 
        A r; 
        B r; //error when i am using this instead of A r;
        C r; //error when i am using this instead of Ar and B r;
        r = a;

        r.callme();
        System.out.println(r.i);//prints 10
        r = b; 
        r.callme(); 
        System.out.println(r.j);//j cannot be resolved or is not a field--what does this mean?
        r = c; 
        r.callme();
        System.out.println(r.k);//k cannot be resolved or is not a field
 

为什么会显示错误?为什么我不能创建 B 或 C 类型的变量 r 并调用 callme() 方法?

已编辑:为了澄清一些事情,我不想使用相同的变量名,我想说的是,而不是 A r;我正在尝试使用 B r 并保持其余代码相同。

【问题讨论】:

不同类型的变量名不能相同(在同一范围内) 【参考方案1】:

不同类型的变量名不能相同(在同一范围内)

修改你的主要方法为

   public static void main(String args[]) 
    A a = new A();
    B b = new B();
    C c = new C();
    A r;
    //you cannot have same variable name for different types (in same scope)
    //B r; // error
    //C r; // error
    r = a;

    r.callme();
    System.out.println(r.i);// prints 10
    r = b;
    r.callme();

    //here you're getting error because object is available at runtime, what you are getting is a compile time error
    System.out.println(r.j);// can be resolved by casting it as System.out.println(((B)r).j)
    r = c;
    r.callme();
    // here you're getting error because object is available at runtime, what you are getting is a compile time error
    System.out.println(r.k);// can be resolved by casting it as System.out.println(((C)r).k);

希望对你有帮助!!

【讨论】:

【参考方案2】:

在运行时,它取决于被引用对象的类型(而不是引用变量的类型),它决定了将执行覆盖方法的哪个版本。

超类引用变量可以引用子类对象。这也称为向上转换。 Java 使用这一事实来解决在运行时对覆盖方法的调用。但反之亦然。

声明 B r1C r2 。您为所有三个类指向相同的变量名称。

通过r= b,您将A 对象引用到r(因为r 已经通过r=a 引用了A)。因此,当您调用 r.j 时,它会给出错误,因为 j 是 B 对象的属性。

r.k case 的解释也一样

【讨论】:

【参考方案3】:

B r; //错误 C r; //错误

出现上述错误是因为您尝试将相同的变量名r 用于不同的类类型 A、B 和 C。由于首先使用了 A,因此在编译和任何后续尝试时都会注册它更改variable r 的类型最终会导致编译时错误。

System.out.println(r.j); System.out.println(r.k);

这些错误发生在编译时,因为在编译期间,class A 中会查找 variable jvariable k。发生这种情况是因为您的 variable r 属于 A 类型。如果您想访问 variable jvariable k,请将 variable r 分别转换为 class Bclass C

希望这会有所帮助!

【讨论】:

但我通过给出 r=b; 将 r 指代为 B 类和 C 类;和 r=c 语句。为什么不考虑呢? 对象分配,即右侧将在运行时出现。对于编译,仅考虑左侧。由于在 LHS 中,变量是 A 类型,因此需要显式转换才能分别访问变量 j 和 k。 这能回答您的问题吗?

以上是关于动态方法分派和运行时多态性错误的主要内容,如果未能解决你的问题,请参考以下文章

64.多态性实现机制—静态分派与动态分派(方法解析静态分派动态分派单分派和多分派)

多态方法调用的解析和分派

深入Java虚拟机之五:多态性实现机制——静态分派与动态分派

Java多态

Java虚拟机 - 多态性实现机制

静态分派&动态分派