zoukankan      html  css  js  c++  java
  • Java问题解读系列之基础相关---含继承时的执行顺序

    今天来研究一下含继承、静态成员、非静态成员时Java程序的执行顺序:

    一、不含继承,含有静态变量、静态代码块

    创建一个子类,该类包含静态变量、静态代码块、静态方法、构造方法

    /**
     * @createtime 2017年3月17日 下午5:17:02
     * @description  创建一个子类
     */
    public class Son{
        public static String name = "子类name";
        
        public static long  date = new Date().getTime();
        
        public String time = String.valueOf(System.currentTimeMillis());
        /**
         * 静态代码块
         */
        static{
            System.out.println("子类静态代码块");
            System.out.println("子类静态代码块日期是:"+String.valueOf(date));
        }
        
        /**
         * 非静态代码块
         */
        {
            System.out.println("子类非静态代码块");
            System.out.println("子类非静态代码块执行时间是:"+time);
        }
        
        /**
         * 静态方法
         * @param names
         */
        public static void getName(String names){
            Son.name = names;
            System.out.println(name);
        }
        
        /**
         * 默认构造方法
         */
        public Son(){
            this("构造son");
            System.out.println("子类默认构造方法");
        }
        
        public Son(String names){
            System.out.println("子类含参构造方法");
            this.name = names;
        }
        
        public static void main(String[] args) {
            getName("son-name");
            new Son();
        }
    }
    
    /*不继承父类时--执行结果如下:
    子类静态代码块
    子类静态代码块日期是:1489742299514
    son-name
    子类非静态代码块
    子类非静态代码块执行时间是:1489742299514
    子类含参构造方法
    子类默认构造方法
    */

    根据执行结果可以很直观的看出,执行顺序是:

    静态代码块->调用的静态方法->非静态代码块->构造方法

    这都是有明显输出情况下看到的顺序,还有一些变量的输出也是有顺序的,只是从结果不太容易看出,但是可以通过断点来调试,在调试之前一定要在所有变量、

    方法及代码块前打上断点,这样看执行顺序就很明了,我打断点之后发现这个程序的整个执行过程是这样的:

    静态变量赋值-->执行静态代码块-->非静态变量赋值-->执行非静态代码块-->调用静态方法-->调用构造方法

    二、含继承、且父类也有静态变量、静态代码块和构造函数

    1、创建一个子类,该类包含静态变量、静态代码块、构造方法

    /**
     * @createtime 2017年3月17日 下午4:25:26
     * @description 定义一个父类
     */
    public class Father {
        
        public static String name = "变量father";
        
        public static long  date = new Date().getTime();
        
        public String time = String.valueOf(System.currentTimeMillis());
        /**
         * 静态代码块
         */
        static{
            System.out.println("父类静态代码块");
            System.out.println("父类静态代码块日期是:"+String.valueOf(date));
        }
        
        /**
         * 非静态代码块
         */
        {
            System.out.println("父类非静态代码块");
            System.out.println("父类非静态代码块执行时间是:"+time);
        }
        
        /**
         * 默认构造方法
         */
        public Father(){
            this("构造father");
            System.out.println("父类默认构造方法");
        }
        
        public Father(String name){
            System.out.println("父类含参构造方法");
            this.name = name;
        }
    
    }
    /*继承父类时-执行结果如下:
    父类静态代码块
    父类静态代码块日期是:1489743876335
    子类静态代码块
    子类静态代码块日期是:1489743876336
    son-name
    父类非静态代码块
    父类非静态代码块执行时间是:1489743876336
    父类含参构造方法
    父类默认构造方法
    子类非静态代码块
    子类非静态代码块执行时间是:1489743876336
    子类含参构造方法
    子类默认构造方法*/

    2、让子类Son继承父类Father

    /**
     * @createtime 2017年3月17日 下午5:17:02
     * @description  创建一个子类
     */
    public class Son extends Father{
        public static String name = "子类name";
        
        public static long  date = new Date().getTime();
        
        public String time = String.valueOf(System.currentTimeMillis());
        /**
         * 静态代码块
         */
        static{
            System.out.println("子类静态代码块");
            System.out.println("子类静态代码块日期是:"+String.valueOf(date));
        }
        
        /**
         * 非静态代码块
         */
        {
            System.out.println("子类非静态代码块");
            System.out.println("子类非静态代码块执行时间是:"+time);
        }
        
        /**
         * 静态方法
         * @param names
         */
        public static void getName(String names){
            Son.name = names;
            System.out.println(name);
        }
        
        /**
         * 默认构造方法
         */
        public Son(){
            this("构造son");
            System.out.println("子类默认构造方法");
        }
        
        public Son(String names){
            System.out.println("子类含参构造方法");
            this.name = names;
        }
        
        public static void main(String[] args) {
            getName("son-name");
            new Son();
        }
    }

    同样打断点调试后发现详细的执行顺序是:


    父类静态变量赋值-->执行父类静态代码块 -->子类静态变量赋值 -->执行子类静态代码块--> 调用子类静态方法--> 父类非静态变量赋值-->执行父类非静态代码块

    -->执行父类构造方法-->子类非静态变量赋值-->执行子类非静态代码块-->执行子类构造函数

    三、结论

    根据以上分析,可以得出以下结论:

    1、实例化一个子类时,优先实例化父类;

    2、静态优先非静态执行;

    3、静态变量优先,其次是静态代码块;

    4、如果子类和父类都有静态成员,则优先执行父类中的静态成员;

  • 相关阅读:
    快速认识 Spring Boot 技术栈
    Spring JDBC Template -实验介绍
    Spring 基于注解的配置 -实验介绍
    Spring 自动扫描与装配 -实验介绍
    Spring IoC 容器 -实验介绍
    Spring 框架的 AOP -实验介绍
    使用 AspectJ 框架实现 Spring AOP
    Spring框架自动创建 proxy
    Spring 框架的 AOP
    考研计算机专业课基础:计算机结构化编程
  • 原文地址:https://www.cnblogs.com/hellowhy/p/6567340.html
Copyright © 2011-2022 走看看