首先说明类在什么情况下被装在到系统中:
1、当用户访问该类的静态成员变量或调用该类的静态方法时,尽管没有使用类创建对象,但是该类将被装入系统。
2、当用户使用new关键字创建一个类的对象时,该类被装入系统。
第二需要了解java中初始化数据域的方法包括:
1、在构造方法中赋值;
2、在声明中赋值;
3、创建初始化块。初始化块又分为静态初始化块和初始化块(格式见下图)。静态初始化块在类第一个被加载的时候调用,仅调用一次,初始化块可多次调用。
初始化的顺序从下面的执行顺序可以看出,首先执行静态初始化块,然后初始化块,最后才是构造方法。静态初始化块仅执行一次。
在某公司面试时碰见的该题目,
- package com.skd.timu;
- public class Demo4 {
- public static void main(String[] args) {
- new childrenDemo();
- new childrenDemo();
- }
- }
- class ParentDemo{
- static String staParentString="父类-静态-变量";
- String parentString="父类-非静态-变量";
- static{
- System.out.println(staParentString);
- System.out.println("父类 - 静态 - 初始化块");
- }
- {
- System.out.println(parentString);
- System.out.println("父类 - 非静态 - 初始化块");
- }
- ParentDemo(){
- System.out.println("父类-构造方法");
- }
- }
- class childrenDemo extends ParentDemo{
- static String staChildrenString="子类-静态-变量";
- String childrenString="子类-非静态-变量";
- static{
- System.out.println(staChildrenString);
- System.out.println("子类 - 静态 - 初始化块");
- }
- {
- System.out.println(childrenString);
- System.out.println("子类- 非静态 - 初始化块");
- }
- childrenDemo(){
- System.out.println("子类-构造方法");
- }
- }
先把程序执行的结果贴上:
- 父类-静态-变量
- 父类 - 静态 - 初始化块
- 子类-静态-变量
- 子类 - 静态 - 初始化块
- 父类-非静态-变量
- 父类 - 非静态 - 初始化块
- 父类-构造方法
- 子类-非静态-变量
- 子类- 非静态 - 初始化块
- 子类-构造方法
- 父类-非静态-变量
- 父类 - 非静态 - 初始化块
- 父类-构造方法
- 子类-非静态-变量
- 子类- 非静态 - 初始化块
- 子类-构造方法
顺序为:
1、父类静态变量——父类静态非初始化块——子类静态变量——子类静态初始化块
2、父类非静态变量——父类初始化块——父类构造方法——子类非静态变量——子类初始化块——子类构造方法
总结为:父类和子类的静态变量和静态初始化块最先执行,变量都优先于初始化块执行。
构造块的加载顺序在静态块之后但在构造方法之前,而且在构造块加载之前,变量已经加载;
构造方法是在静态变量,静态块,变量,构造块后才加载的,是在类实例化时,除了调用方法外的最后加载的位置;
因为静态变量和静态块都是全局的,因此在程序加载时就已经加载,不会因为是子类中的静态变量和静态块就比父类的构造块加载晚,但在都是静态变量或静态块的情况下,
总是先初始化父类的,然后初始化子类的。
同样的因为构造块和构造方法不是全局的,而且子类在实例化时总是先调用父类的构造块和构造方法,因此父类的构造块和构造方法在子类的之前调用。即在实例化子类时,程序会先调用父类的实例化构造块或者构造方法,然后才会调用子类的构造块和构造方法完成子类的实例化。
而且,构造块和构造方法会在每次实例化的时候都执行,静态变量和静态块只会执行一次(不管该类实例化多少对象)。