类的加载

public class Test{
    public static void main(String[] args) {
        Father ts = new Son();
    }
}

class Father {
    {
        System.out.println("父类 非静态块 1  执行");
    }
    static {
        System.out.println("父类 static块 1  执行");
    }
    static Sample staticSam1 = new Sample("父类 静态成员 staticSam1 初始化");
    Sample sam1 = new Sample("父类 普通成员 sam1 初始化");
    static Sample staticSam2 = new Sample("父类 静态成员 staticSam2 初始化");
    static {
        System.out.println("父类 static块 2  执行");
    }

    Father() {
        System.out.println("父类 默认构造函数被调用");
    }

    Sample sam2 = new Sample("父类 普通成员 sam2 初始化");

    {
        System.out.println("父类 非静态块 2  执行");
    }

}

class Son extends Father {
    {
        System.out.println("子类 非静态块 1  执行");
    }

    static Sample staticSamSub1 = new Sample("子类 静态成员 staticSamSub1 初始化");

    Son() {
        System.out.println("子类 默认构造函数被调用");
    }

    Sample sam1 = new Sample("子类 普通成员 sam1 初始化");
    static Sample staticSamSub2 = new Sample("子类 静态成员 staticSamSub2 初始化");

    static {
        System.out.println("子类 static块1  执行");
    }

    Sample sam2 = new Sample("子类 普通成员 sam2 初始化");

    {
        System.out.println("子类 非静态块 2  执行");
    }

    static {
        System.out.println("子类 static块2  执行");
    }
}

class Sample {
    Sample(String s) {
        System.out.println(s);
    }

    Sample() {
        System.out.println("Sample默认构造函数被调用");
    }
}





运行结果:
父类 static1  执行
父类 静态成员 staticSam1 初始化
父类 静态成员 staticSam2 初始化
父类 static2  执行
子类 静态成员 staticSamSub1 初始化
子类 静态成员 staticSamSub2 初始化
子类 static1  执行
子类 static2  执行
父类 非静态块 1  执行
父类 普通成员 sam1 初始化
父类 普通成员 sam2 初始化
父类 非静态块 2  执行
父类 默认构造函数被调用
子类 非静态块 1  执行
子类 普通成员 sam1 初始化
子类 普通成员 sam2 初始化
子类 非静态块 2  执行
子类 默认构造函数被调用

[例子来源](http://blog.youkuaiyun.com/u011080472/article/details/51330114)

顺序:子类初始化过程:父类static代码块执行顺序–》父类static成员变量并且初始化其构造函数–》子类static代码块–》子类static成员变量并且初始化其构造函数–》父类成员变量并且初始化其构造函数–》父类构造函数–》子类成员变量并且初始化其构造函数–》子类变量的构造函数;
也就是说,每个类加载的时候,成员变量的初始化先于构造器,从JVM类加载采用父亲委托机制!加载器会首先委托自己的父加载器去加载该类,若父加载器能加载,则由父加载器完成加载任务,否则才由自加载器去加载。

public class testStatic {
    public static void main(String args[]){
        Singleton singleton=Singleton.getInstance();
        System.out.println(singleton.count1);
        System.out.println(singleton.count2);
    }
}

class Singleton{
    private static Singleton singleton=new Singleton();
    public static int count1;
    public static int count2=0;

    private Singleton(){
        count1++;
        count2++;
    }

    public static Singleton getInstance(){
        return singleton;
    }
}


运行结果:
1
0

class Singleton{

    public static int count1;
    public static int count2=0;
    private static Singleton singleton=new Singleton();//调换了位置
    private Singleton(){
        count1++;
        count2++;
    }

    public static Singleton getInstance(){
        return singleton;
    }
}

运行结果:
1
1

为什么呢?
第一个为count2为0的原因是被赋值了两次,
而第二个在count2初始化之后再进行++操作所以变成了1.

类加载过程:
一、加载
类的加载指的是将类的.class文件中二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个
java.lang.Class对象,用来封装类在方法区内的数据结构。在这个阶段,会执行类中声明的静态代码块。也就是类中的静态块执行时不需要等到类的初始化。

二、连接
类加载完成后就进入了类的连接阶段,连接阶段主要分为三个过程分别是:验证,准备和解析。在连接阶段,主要是将已经读到内存的类的二进制数据合并到虚拟机的运行时环境中去。

三、初始化
在这个阶段主要执行类的构造方法。并且为静态变量赋值为初始值,执行静态块代码。

引用地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值