创建子类的对象作为Java中超类的实例

时间:2014-07-09 11:40:46

标签: java inheritance

说,我有以下代码(这是一个测验问题,所以我可以在我的IDE中运行它,但逻辑如何工作对我来说不太清楚):

public class Test {

    public static void main(String[] args){
        A aInstance1 = new A();
        A aInstance2 = new B();
        A aInstance3 = new C();
        aInstance1.doSth();
        aInstance2.doSth();
        aInstance3.doSth();
    }
}

class A {
    public static void doSth(){
        System.out.println("Doing something in A");
    }
}
class B extends A {
    public static void doSth(){
        System.out.println("Doing something in B");
    }
}

class C extends B {
    public static void doSth(){
        System.out.println("Doing something in C");
    }
}

输出如下:

在A 中做某事

在A 中做某事

在A 中做某事

因此,我的第一个问题是:声明的含义是什么,如

A aInstance2 = new B();

即,为什么要创建一个B类对象,将其声明为A类的实例?与声明

相比,作为B类对象的aInstance2的属性如何变化
B aInstance2 = new B();

如果我从类A,B和C中的方法doSth()的声明中删除 static 这个词,则输出变为

在A 中做某事

在B 中做某事

在C 中做某事

因此,当方法是静态的时,类A的方法doSth()没有被子类的方法覆盖,输出总是“在A中做某事”由不同类的对象,而当它成为一个实例(非静态)方法时,它被覆盖(如果我在这里使用正确的术语)。为什么会这样?

5 个答案:

答案 0 :(得分:1)

删除静态这个词你正在做动态绑定,因为你几乎都在说:"尽管我知道这个对象属于A型,我希望它的行为像B"。

添加单词static意味着您正在使该方法成为类[引用类型]的一部分,并且每次调用时:" A dosmth()"他知道它只适用于A,所以它显示了A类的方法结果。

至于你会做什么?我从学校那里学到了这个功能,当我决定去采访时更加研究它;这是面试官想要看到的事情之一,如果你能处理的话

如果您不介意,我会发布一个包含静态和动态绑定信息的链接 http://javarevisited.blogspot.ro/2012/03/what-is-static-and-dynamic-binding-in.html

答案 1 :(得分:1)

因为静态方法基于参考类型

aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();

所以在内部它转换为:

A.doSth();
A.doSth();
A.doSth();

答案 2 :(得分:1)

静态方法是类方法,而非静态方法是实例方法。因此,当您在实例上调用静态方法时,实际上是通过此实例的声明类型调用它。因此,以下所有调用实际上都执行相同的调用:A.doSth(),因为所有实例都声明为类型A.

aInstance1.doSth();
aInstance2.doSth();
aInstance3.doSth();

删除static关键字后,doSth()方法将成为实例方法。实例方法是在对象而不是类上执行的。此外,当您在子类中重新声明实例方法时,此方法将被子类覆盖。在您的示例中,B类和C类覆盖doSth()。因此,每个类都提供自己的实现。

答案 3 :(得分:1)

覆盖 取决于拥有类的实例。静态方法与类的任何实例都没有关联,因此该概念不适用。

使静态方法更快,因为没有必要等到运行时才能确定要调用哪种方法。

在Java中覆盖 只是意味着将根据对象的运行时类型调用特定方法,而不是基于它的编译时类型。

插图 -

  • 当doSth()是静态的时:

    A aInstance1 = new A();
    A aInstance2 = new B();
    A aInstance3 = new C();
    aInstance1.doSth();
    aInstance2.doSth();
    aInstance3.doSth();
    

在上面的代码中,编译器将在编译时确定没有实例应该为A调用。否覆盖。

  • 当doSth()不是静态时:

    A aInstance1 = new A();
    A aInstance2 = new B();
    A aInstance3 = new C();
    aInstance1.doSth();
    aInstance2.doSth();
    aInstance3.doSth();
    

在上面的代码中,编译器将在运行时决定该方法不是静态的,并且应该被相应的实例覆盖。

答案 4 :(得分:0)

静态方法处于class级别并且作用于引用类型(LHS ==),而不像基于实例类型(RHS ==)动态分派的实例级方法