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型也是同样的结果。

原文地址:https://www.cnblogs.com/bossen/p/6145038.html