解释:为什么枚举类的静态代码块再实例代码块之后?????

/**
 *
 * 以下是我的个人理解
 *
 *一 创建一个类的对象时,触发该继承树的初始化
 *    继承树的执行过程
 *       总体上先初始化静态树,在初始化实例树
 *           初始化静态树: 总体:Object到目标类,当前类:静态变量和静态代码块按先后顺序,
 *           初始化实例树: 总体:Object到目标类,当前类:实例变量和实例代码块按先后顺序,再执行构造器
 *    继承树的执行方式
 *       实例树中的执行顺序:(通过堆栈的方式去实现)
 *          执行当前类构造器通过(显式,隐式,间接通过本类重载的构造器)申请一次父类的构造器的调用
 *          自底向上确定要执行或初始化哪些类的实例代码块,实例变量,构造器,
 *          再自顶向下的去执行这些内容
 *        静态树也是如此(通过堆栈的方式去实现)
 *           自底向上确定继承了哪些类静态变量或静态代码块(相当于列一个清单(^_^)),然后再自顶向下初始化这些类的静态变量或静态代码块
 *  注意: 类的初始化只执行一次(即静态树只执行一次)
 *
 *二疑问
 * 内部类的实例化也是按照如上规则进行的,有一点不太理解,似乎枚举有一些不同,代码如下
 * 为什么枚举类的静态代码块再实例代码块之后?????
 *
 *三 测试
 *  本人水平有限,做了如下测试,现在创建一个A类,并且保证A类代码和C枚举几乎一样,如下
 *  1  给A类声明实例变量SUMMER,用public static final修饰(枚举的实例也是如此,而且是默认的)
 *  2  给A提供无参的构造器和实例代码块
 *  3  在A的静态代码块里给SUMMER创建一个A的实例变量赋值给它(唯一明显的区别)
 *  点击运行,哇输出结果居然也一样,大家看出了什么??好像把A类几乎改造成了一个枚举类.
 *
 *四 如下揣测:
 *    1 现在知道终于为什么枚举的实例默认public static final修饰了,
 *         因为final的静态成员变量,要么声明时赋值,要么在静态代码块里,而且final类型的变量有保证了它的不可变性
 *    2 枚举类其实就是把成员变量放在静态代码块里显式赋值执行初始化了.就像在A的静态代码块里出现的SUMMER = new A();
 *         现在正好解释了开头我的疑问:为什么枚举类的静态代码块再实例代码块之后?????
 *         比如枚举类C在静态代码块里显式创建了一个该类的对象并且赋值了实例变量SPRING,造成了实例代码块与静态代码块同步.
 *    3 枚举其实就是普通类(从它默认继承Enum也可以看出),但不能当成完全当成普通类去用
 *          (想一想@interface注解和interface接口也是一样,注解默认继承了Annotation接口,但不能当成完全当成接口去用)
 *    4 人家设计枚举类就是希望这类的实例的个数有限而且是确定的.所以连构造器都是private的,而且加入它一些特殊的语法
 *
 *
 */
//枚举类:  解释:为什么枚举类的静态代码块再实例代码块之后?????
public  class EnumQuestion {

    public static void main(String[] args) throws Exception{
        System.out.println(C.SPRING);
        System.out.println("=====================");
        System.out.println(A.SUMMER);

        /**运行代码如下
         *
         * 我是C的实例代码块
         * 我是C的构造器
         * 我是C的静态代码块
         * SPRING
         * =====================
         * 我是A的实例代码块
         * 我是A的参构造器
         * 我是A的静态代码块
         * com.china.school.疑问.A@2133c8f8
         */
    }
}

enum C {
    SPRING;
    static {
        System.out.println("我是C的静态代码块");
    }
    {
        System.out.println("我是C的实例代码块");
    }
    C(){
        System.out.println("我是C的构造器");
    }
}

class A{
    public static final A SUMMER ;
    public A(){
        System.out.println("我是A的参构造器");
    }
    {
        System.out.println("我是A的实例代码块");
    }
    static  {
        SUMMER = new A();
        System.out.println("我是A的静态代码块");
    }

}

 

posted @ 2022-05-15 12:14  -和时间赛跑-  阅读(363)  评论(0编辑  收藏  举报