我需要知道控制流是什么以及这段代码究竟发生了什么?

时间:2013-06-20 15:18:55

标签: java inheritance

我写了这段代码:

class A {
    int a;

    void method() {
        System.out.println("Overridden method of Class A called!");
    }

    void method2() {
        System.out.println("Normal Method of Class A called!");
    }
}

class B extends A {
    int b;

    void method() {
        System.out.println("Overridden method of Class B called!");
    }

    void method1() {
        System.out.println("Normal Method of Class B called!");
    }
}

class C {
    public static void main(String[] args) {
        A a1 = new A();
        B b1 = new B();
        a1 = b1; // ***Line 1***
        System.out.println("After referencing!");
        a1.method();
        a1.method2();

        A a2 = new B(); // ***Line 2***
        a2.method();
        a2.method2();
    }
}

第1行和第2行位于上面标有评论的代码中

现在,我对 第1行 的物理意义有所了解,但 第2行 意思是? 如何将内存分配给类型A的对象“ a2 ”?这种对象的性质和行为是什么?它与正常实例有何不同? 第1行 第2行 是否表达相同的含义?如果是这样,怎么样?如果不是,它们有何不同,因为它们显然会提供相同的输出。

5 个答案:

答案 0 :(得分:1)

他们是一样的。在Java中,所有对象引用都保持相同的内存量。因此,相同的Object引用的内存空间可以指向任何Java对象。编译器强制您仅指定引用A以指向扩展A的类的Object。在上述两种情况下,您都有A类型的引用(C中的指针),该引用指向类B的实例。

答案 1 :(得分:1)

a2是[类型A]的引用类型,它引用了类型B的对象。仅此而已。

是Line1和Line 2是一回事。只是做同样事情的不同方式。

答案 2 :(得分:1)

两者都是等价的,但唯一不同的是,在第一个你不必要地创建了一个Anew A();),你只是扔掉了。

A a1 = new A(); // new A() should not be done here
B b1 = new B();
a1 = b1; // ***Line 1***

最好按照以下方式进行 -

//A a1 = new A(); // new A() should not be done here
B b1 = new B();
A a1 = b1; // ***Line 1***

它们是相似的,因为在这两种情况下,您都要实例化Bnew B();)的对象,并创建类型为A的变量来引用该实例。

答案 3 :(得分:1)

这两行与以下

类似
Object obj = new SomeClass();

但是在Line1中,正在创建一个类型A的额外对象。

所以用

    A a1 = new A();  // a new object
    B b1 = new B();  // another object
    a1 = b1; // make a1 point to the b1 and lose the reference to original `A` type object

    A a2 = new B(); // create a new `B` object and assign it to reference of `A` type.

所以基本上是相同的(除了line1中的额外对象)

<强>但是

这两行内部使用polymorphism的概念。

答案 4 :(得分:1)

总是尝试编写接口而不是具体实现,除非您发现它适合的情况(比如来自Swing的类,其中UI组件具有具体实现,但您可以覆盖它以获得更好的UI或UI选择)。

现在考虑一下你的情况,如果我只是针对不同的行为(即不同的方法实现)做这种继承,我会更喜欢一个接口'I',它由A类和B类实现。这就是它开始变得更有意义的地方。

以上解释了设计视角。

现在从编码的角度来看。超类总是引用子类对象。但是当你访问一个方法时,它的方法是被调用的对象,但是引用类型的方法。

A a1 = new A();//Object of A in heap which is referred by reference of A
        B b1 = new B();//Object of B in heap which is referred by reference of B
        a1 = b1; // ***Line 1*** Here super type(a1) is referring to subtype b1. So actual object is that of class B.
        System.out.println("After referencing!");
        a1.method();//method from actual object is called ie b1
        a1.method2();//same

        A a2 = new B(); // ***Line 2*** again object created in heap is of type B but its referred by super type A
        a2.method();//and hence,method called is from B class not from class A
        a2.method2();