• Java 多态方法构造器执行方法


    我们参考下面这个例子:

    读者可以提前考虑一下,这段程序的输出会是什么。

    public class Polymorphism {
    
        /**
         * 创建一个类A
         * 该类中有一个方法draw,以及一个构造方法A
          */
        static class A{
            void draw(){
                System.out.println("A.draw()");
            }
            A(){
                System.out.println("A() before draw()");
                draw();
                System.out.println("A() after draw()");
            }
        }
    
        /**
         * 创建一个类B,继承A
         * 该类中同样有一个方法draw,以及一个构造方法B
         */
         static class B extends A {
             private int value=1;
            void draw(){
                System.out.println("B.draw(),value="+value);
            }
            B(int v){
                value=v;
                System.out.println("B.B(),value="+value);
             }
        }
        
        /*现在我们调用B的构造函数,构造一个B*/
        public static void main(String[] args) {
            new B(5);
        }
    }

    最后的输出结果为

    A() before draw()
    B.draw(),value=0
    A() after draw()
    B.B(),value=5

    初次分析

    可见,当我们试图构造一个B时,应该会优先构造B的父类A,所以会调用父类A的构造函数A(),所以会输出

    A() before draw()

    这时A调用了draw()方法,因为是构造B类,而B类覆盖重写A类的draw()方法,所以这里应该调用的是B类重写过后的draw()方法,而B类的value默认值为1,所以会输出

    B.draw(),value=1
    A() after draw()

    此刻父类A已经完成构造,所以接着才会构造B,调用B的构造函数B(),且传入的值为5,所以会输出

    B.B(),value=5

    而实际上,最后输出的并不是

    B.draw(),value=1

    而是

    B.draw(),value=0

    最后在《Thinking in Java》一书中找到了类似的例子,其中给出了一套正确的初始化顺序


    (1)在其他任何事物之前,将分配给对象的存储空间初始化为二进制的零

    (2)如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法  (要在调用B构造器之前调用),由于步骤1的缘故,我们此时会发现value的值为0。

    (3)按照声明的顺序调用成员的初始化方法。

    (4)调用导出类的构造器主体。

  • 相关阅读:
    《鱼嘤嘤小分队》第一次作业:项目选题
    第一次博客作业
    csp 201709-2 优先队列模拟
    csp 201403-2
    csp 201809-2 买菜
    JavaScript中伪协议
    修改placeholder的样式
    jQuery对象与DOM对象之间的转换方法
    a的样式
    Guid.NewGuid() 和 new Guid()的区别
  • 原文地址:https://www.cnblogs.com/rekent/p/7712321.html
Copyright © 2020-2023  润新知