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)

猜你喜欢

转载自www.cnblogs.com/lyldelove/p/12710179.html