• java类的初始化顺序


    最近项目上工作强度还是蛮紧张的,技术还是公司框架自身封装好的(spring+mvc+mybatis+js+jquery+json+shiro+cacheEnable+swagger+ajax+反射等等几十项框架及插件),基础的原理还是没有脱离java的基础知识。今天抽个空把java类的初始化顺序整理一下(最近发现的一个规律,我之前用心总结的博客内容,在工作中用到的频次还是非常高的,所以好记性不如烂笔头,坚持总结、实践吧,骚年)。

    一、构造器初始化

    package com.edu;
    
    class Window {
        Window(int marker) {
            System.out.println("window(" + marker + ")");
        }
    }
    
    class House {
        Window w1 = new Window(1);
    
        House() {
            w3 = new Window(33);
        }
    
        Window w2 = new Window(2);
    
        void f() {
            System.out.println("f()");
        }
    
        Window w3 = new Window(3);
    }
    
    public class OrderOfInitialization {
        public static void main(String[] args) {
            House h = new House();
            h.f();
        }
    }
    结果:
    window(1)
    window(2)
    window(3)
    window(33)
    f()

    ①:初始化可以放在构造器内部;

    ②:House类在new对象时,会对内部的所有变量进行初始化,所以你看到的是先进行window(1)、window(2)、window(3)的初始化;

    ③:window(3)被初始化了两次

    二、静态数据的初始化

    package com.edu;
    
    /**
     * 静态数据的初始化
     * 
     * @author tery
     *
     */
    class Bowl {
        Bowl(int marker) {
            System.out.println("Bowl(" + marker + ")");
        }
        void f1(int marker) {
            System.out.println("f1(" + marker + ")");
        }
    }
    
    class Table {
        static Bowl bowl1 = new Bowl(1);
    
        Table() {
            System.out.println("Table");
            bowl2.f1(1);
        }
        void f2(int marker) {
            System.out.println("f2(" + marker + ")");
        }
        static Bowl bowl2 = new Bowl(2);
    }
    
    class CupBoard {
        Bowl bowl3 = new Bowl(3);
        static Bowl bowl4 = new Bowl(4);
    
        CupBoard() {
            System.out.println("CupBoard()");
            bowl4.f1(2);
        }
        void f3(int marker) {
            System.out.println("f3(" + marker + ")");
        }
        static Bowl bowl5 = new Bowl(5);
    }
    
    public class StaticInitialization {
        public static void main(String[] args) {
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
    //        System.out.println("Creating new CupBoard() in main");
    //        new CupBoard();
    //        table.f2(1);
    //        cupboard.f3(1);
        }
    //    static Table table=new Table();
    //    static CupBoard cupboard=new CupBoard();
    }

    结果:
    Creating new CupBoard() in main
    Bowl(4)
    Bowl(5)
    Bowl(3)
    CupBoard()
    f1(2)

    为了看清楚,把注释掉的代码逐步放开:
    public class StaticInitialization {
        public static void main(String[] args) {
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
    //        System.out.println("Creating new CupBoard() in main");
    //        new CupBoard();
    //        table.f2(1);
    //        cupboard.f3(1);
        }
        static Table table=new Table();
    //    static CupBoard cupboard=new CupBoard();
    }
    结果:
    Bowl(1)
    Bowl(2)
    Table
    f1(1)
    Creating new CupBoard() in main
    Bowl(4)
    Bowl(5)
    Bowl(3)
    CupBoard()
    f1(2)
    public class StaticInitialization {
        public static void main(String[] args) {
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
    //        System.out.println("Creating new CupBoard() in main");
    //        new CupBoard();
    //        table.f2(1);
    //        cupboard.f3(1);
        }
        static Table table=new Table();
        static CupBoard cupboard=new CupBoard();
    }
    结果:
    Bowl(1)
    Bowl(2)
    Table
    f1(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    CupBoard()
    f1(2)
    Creating new CupBoard() in main
    Bowl(3)
    CupBoard()
    f1(2)
    public class StaticInitialization {
        public static void main(String[] args) {
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
    //        table.f2(1);
    //        cupboard.f3(1);
        }
        static Table table=new Table();
        static CupBoard cupboard=new CupBoard();
    }
    结果:
    Bowl(1)
    Bowl(2)
    Table
    f1(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    CupBoard()
    f1(2)
    Creating new CupBoard() in main
    Bowl(3)
    CupBoard()
    f1(2)
    Creating new CupBoard() in main
    Bowl(3)
    CupBoard()
    f1(2)
    public class StaticInitialization {
        public static void main(String[] args) {
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
            System.out.println("Creating new CupBoard() in main");
            new CupBoard();
            table.f2(1);
            cupboard.f3(1);
        }
        static Table table=new Table();
        static CupBoard cupboard=new CupBoard();
    }
    结果:
    Bowl(1)
    Bowl(2)
    Table
    f1(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    CupBoard()
    f1(2)
    Creating new CupBoard() in main
    Bowl(3)
    CupBoard()
    f1(2)
    Creating new CupBoard() in main
    Bowl(3)
    CupBoard()
    f1(2)
    f2(1)
    f3(1)

    小总结:

    ①无论创建多少个对象,静态数据都只占一份存储区域。static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且没有对它进行初始化,那么它就会获得基本类型的标准初值,如果它是对象的引用,那么它的默认初始化的值就是null。

    ②初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化),而后是非静态对象。

    ③要执行main()(静态方法),必须加载StaticInitialization类,紧接着其静态域table和cupboard被初始化,这将导致他们对应的类也被加载,并且由于它们也都包含静态的Bowl对象,因此Bowl随后也被加载。

    三、.class创建对象

    package com.edu;
    
    import java.util.Random;
    
    /**
     * .class属性的初始化
     * @author tery
     *
     */
    class Initable{
        Initable(){
            System.out.println("Initable initial...");
            }
        static final String staticFinal="47";
        static final int staticFinal2=ClassInitialization.rand.nextInt(1000);
        static{
            System.out.println("Initializing Initable");
        }
    }
    class Initable2{
        static int staticNonFinal=147;
        static{
            System.out.println("Initializing Initable2");
        }
    }
    class Initable3{
        static int staticNonFinal =74;
        static {
            System.out.println("Initializing Initable3");
        }
    }
    public class ClassInitialization {
    public static Random rand=new Random(47);
    public static void main(String[] args){
        Class initable=Initable.class;
        System.out.println("After creating Initable ref");
        System.out.println(Initable.staticFinal);
        Initable a=new Initable();
        System.out.println(Initable.staticFinal2);
    //    System.out.println(Initable2.staticNonFinal);
    //    System.out.println(Initable3.staticNonFinal);
    }
    }
    结果:
    After creating Initable ref
    47
    Initializing Initable
    Initable initial...
    258

    为了使用类而准备的工作实际上包含三个步骤:

    ①加载,这是由类加载器执行的,该步骤将查找字节码(通常在classpath所指定的路径中查找,但这并非是必须的),并从这些字节码中创建一个Class对象。

    ②链接,在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类创建的对其他类的所有引用。

    ③初始化,如果该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化块。初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行。

    ④在打印Initable.staticFinal时属于调用常数静态域,即使加上Initable(){...}的构造方法,也不会执行,将int型改为String型也是同样的结果。

  • 相关阅读:
    NGINX+uWsgi部署Django项目
    centos7 docker启动服务,无法通过宿主机ip进行访问
    基于docker 搭建Prometheus+Grafana
    centos7安装MySQL5.7
    centos7下安装python7
    loadrunner27257问题解决办法
    学习Python+selenium自动化感想
    find_element和find_elements
    正则表达式
    Jdk自带的Windows性能监控工具JVM
  • 原文地址:https://www.cnblogs.com/bossen/p/6145038.html
Copyright © 2020-2023  润新知