zoukankan      html  css  js  c++  java
  • 再探Java中的继承加载顺序

    public class test2 {
    
         static class a {
            int x = 999;
            int y = 999;
            {
                System.out.println("a--父类非静态方法");
            }
            static {
                System.out.println("a--父类静态方法");
            }
            // public a() {
            //     System.out.println("a--执行a类无参构造方法");
            // }
            public a(int x) {
    
                System.out.println("a--执行父类有参构造方法");
            }
            public void print() {
                System.out.println("a--我是父类的打印方法");
            }
        }
    
        static class b extends a {
            int x = 1;
            int y;
            {
                System.out.println("b--子类非静态方法");
            }
            static {
                System.out.println("b--子类静态方法");
            }
            // public b() {
            //     super();
            //     System.out.println("b--执行b类无参构造方法");
            //     //y = -1;
            // }
            public b(int x) {
                super(1);
                System.out.println("b--执行子类有参构造方法");
            }
            public void print() {
                System.out.println("b--在子类中调用父类的super方法");
                super.print();
                System.out.println("b--我是子类的打印方法");
            }
        }
    
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int x = 0;
            new b(x);
            //a.print();
        }
    
    }
    


    如图,这样加载顺序,先加载的都是静态块,先父类后子类。然后加载父类的非静态方法和构造器,然后子类的非静态方法和构造器

    执行顺序大体上可以说是先父类后子类,父类static域 ==》子类static域 ==》父类数据成员域 ==》父类构造器 ==》子类数据成员域 ==》子类构造器。而且从结果中我们还可以看到,无论实例化多少个对象,static 域仅有一份,而且只执行一次。

    注意第三十九行代码:这里显式调用了父类的有参构造,不加的话会默认调用无参的,如果父类没写无参的就会报错



    第二个:

        public class test1 {
    
             static class a {
                int x = 999;
                int y = 999;
                {
                    System.out.println("a--父类非静态方法");
                }
                static {
                    System.out.println("a--父类静态方法");
                }
                public a() {
                    System.out.println("a--执行a类无参构造方法");
                    print();
                }
                public a(int x) {
                    System.out.println("a--执行父类有参构造方法");
                }
                public void print() {
                    System.out.println("a--我是父类的打印方法");
                }
            }
    
            static class b extends a {
                int x = 1;
                int y;
                {
                    System.out.println("b--子类非静态方法");
                }
                static {
                    System.out.println("b--子类静态方法");
                }
                public b() {
                    System.out.println("b--执行b类无参构造方法");
                    //y = -1;
                }
                public b(int x) {
                    // super(1);
                    //不写是默认生成的super(),无参数的
                    System.out.println("b--执行子类有参构造方法");
                }
                public void print() {
                    System.out.println("b--在子类中调用父类的super方法");
                    super.print();
                    System.out.println("b--我是子类的打印方法");
                }
            }
    
    
            public static void main(String[] args) {
                // TODO Auto-generated method stub
                int x = 0;
                a a1 = new a(x);
                a1.print();
                System.out.println();
                b b1 = new b(x);
    
                // a.print();
            }
    
        }
    


    输出如图:

    第二个声明了子类的对象,因为print(),在子类中被重写了。所以调用的是子类的重写后的print方法。但是还是可以通过super访问父类的这个被重写的方法。

    子类的构造器必须要调用父类的构造器才能完成初始化,默认的是super(),没有参数的,也就是会默认调用父类无参数的构造器


    第三个:

        public class test1 {
    
             static class a {
                int x = 999;
                int y = 999;
                {
                    System.out.println("a--父类非静态方法");
                }
                static {
                    System.out.println("a--父类静态方法");
                }
                // public a() {
                //     System.out.println("a--执行a类无参构造方法");
                //     print();
                // }
                public a(int x) {
                    System.out.println("a--执行父类有参构造方法");
                }
                public void print() {
                    System.out.println("a--我是父类的打印方法");
                }
            }
    
            static class b extends a {
                int x = 1;
                int y;
                {
                    System.out.println("b--子类非静态方法");
                }
                static {
                    System.out.println("b--子类静态方法");
                }
                public b() {
                     super(0);
                    System.out.println("b--执行b类无参构造方法");
                    //y = -1;
                }
                public b(int x) {
                    super(1);
                    //不写是默认生成的super(),无参数的
                    System.out.println("b--执行子类有参构造方法");
                }
                public void print() {
                    System.out.println("b--在子类中调用父类的super方法");
                    super.print();
                    System.out.println("b--我是子类的打印方法");
                }
            }
    
    
            public static void main(String[] args) {
                // TODO Auto-generated method stub
                int x = 0;
                // a a1 = new a(x);
                // a1.print();
                System.out.println();
                b b1 = new b(x);
    
                // a.print();
            }
    
        }
    

           如果注释了父类的无参构造,但是子类还有有无参构造,我现在创建的是子类有参的对象,还是会报错。为什么?问了杨学长,语法规定就是这样,就算这个b子类无参构造没有实际加载(打印信息没有打印),只要你写了子类的构造,你就必须要为这个构造方法负责,不管在之后对象有没有用到。注释了父类无参构造的话,可以在b子类无参构造这里加一个super(0),调用父类有参的构造,必须要特别这样声明才行,不声明编译器会找父类无参,无参又没有,所以报错。

           编译器按照Java语言的规范把源码编译成字节码文件,然后JVM加载这个类,初始化等一系列操作调用它的main方法。所以说编译的时候会检查你的语法是否正确,不是说不用就检查了,编译时能发现的错误,不会拖延到运行时才知道

  • 相关阅读:
    Python中with用法详解
    SVM-支持向量机总结
    shell 脚本总结
    pycharm git 用法总结
    python小实例——tkinter实战(计算器)
    PyCharm 使用技巧
    博客园博文生成章节目录
    Chrome安装crx文件的插件时出现“程序包无效”
    Matplotlib pyplot中title() xlabel() ylabel()无法显示中文(即显示方框乱码)的解决办法
    Pandas-高级部分及其实验
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/7256673.html
Copyright © 2011-2022 走看看