zoukankan      html  css  js  c++  java
  • Java Web(二) 类的初始化及初始化顺序

    1. 问题点

    最近在写单例模式的时候碰到了@Autiwired注解注入为NULL的情况,研究一番,发现是和类的初始化顺序有关。先抛出我的问题:

    //异步处理
    public class AsyncManager {
    
        @Autowired
        ScheduledExecutorService scheduledExecutorService;
    
        /**
         * 操作延迟10毫秒
         */
        private final int OPERATE_DELAY_TIME = 10;
    
        /**
         * 静态AsyncManager,单例
         */
        private static AsyncManager manager = new AsyncManager();
    
        /**
         * 无参构造函数
         */
        private AsyncManager(){}
    
        /**
         * 单例模式(饿汉式)
         * @return AsyncManager
         */
        public static AsyncManager getManager() {
            return manager;
        }
    
        public void execute(TimerTask task) {
            scheduledExecutorService.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
        }
    
    }
    
    public SysUser login(String username, String password) {
        AsyncManager.getManager().execute(new TimerTask() {
            @Override
            public void run() {
                System.out.println(123);
            }
        });
        return null;
    }
    

    问题点:

    在调用AsyncManager.getManager().execute()的方法时,scheduledExecutorServiceNULL,并未引入。

    原因:

    @Autowired一定要等本类构造完成后,才能从外部引用设置进来。调用AsyncManager.getManager().execute()的方法时,scheduledExecutorService还没有注入进来,这也是为什么@Autowired注解推荐写在构造器或者方法上。

    2. 类的初始化顺序

    由上面的问题,引申出来类的初始化和初始化顺序问题。

    先看测试代码:

    public class Dog {
    
        public static int a;
        public int b;
    
        static {
            System.out.println("Static{} a, " + a++);
        }
    
        {
            System.out.println("{} a, " + a++);
            System.out.println("{} b, " + b++);
        }
    
        public Dog() {
            System.out.println("Construct a, " + a++);
            System.out.println("Construct b, " + b++);
        }
    
        public static void show() {
            System.out.println("show() a, " + a++);
        }
    
        public void display() {
            System.out.println("display() a, " + a++);
            System.out.println("display() b, " + b++);
        }
    
        public static void main(String[] args) {
            //Dog.show();
            //System.out.println(Dog.a);
            new Dog();
        }
    }
    

    main方法中执行new Dog()时,程序运行结果为:

    Static{} a, 0
    {} a, 1
    {} b, 0
    Construct a, 2
    Construct b, 1
    

    结果说明初始化顺序为:

    Static成员变量 -> Static代码块 -> 普通成员变量 -> 普通代码块 -> 构造函数

    如果有继承关系,则顺序为:父类Static成员变量 -> 父类Static代码块 -> 子类Static成员变量 -> 子类Static代码块 -> 父类普通成员变量 -> 父类普通代码块 -> 子类普通成员变量 -> 子类普通代码块 -> 父类构造函数 -> 构造函数

    3. 类什么时候初始化

    • 创建类的实例的时候,即new一个对象
    • 访问某个类或接口的静态变量,或者对该静态变量赋值
    • 调用类的静态方法
    • 反射
    • 初始化一个类的子类(会首先初始化子类的父类)
    • JVM启动时标明的启动类,即文件名和类名相同的那个类

    类什么时候初始化参考Java中类的加载顺序介绍(ClassLoader)

  • 相关阅读:
    Redis做为缓存的几个问题
    Python——操作smb文件服务器(上传和下载)
    Python——assert、isinstance的用法
    centos7-修改默认python为3
    mqtt
    如何编译生成 mkfs.ubifs、ubinize 工具
    2020-2笔记
    2020-1笔记
    C语言中getopt()和getopt_long()函数的用法
    buildroot
  • 原文地址:https://www.cnblogs.com/lyldelove/p/12710179.html
Copyright © 2011-2022 走看看