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默认构造函数被调用");
}
}
运行结果:
父类 static块 1 执行
父类 静态成员 staticSam1 初始化
父类 静态成员 staticSam2 初始化
父类 static块 2 执行
子类 静态成员 staticSamSub1 初始化
子类 静态成员 staticSamSub2 初始化
子类 static块1 执行
子类 static块2 执行
父类 非静态块 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对象,用来封装类在方法区内的数据结构。在这个阶段,会执行类中声明的静态代码块。也就是类中的静态块执行时不需要等到类的初始化。
二、连接
类加载完成后就进入了类的连接阶段,连接阶段主要分为三个过程分别是:验证,准备和解析。在连接阶段,主要是将已经读到内存的类的二进制数据合并到虚拟机的运行时环境中去。
三、初始化
在这个阶段主要执行类的构造方法。并且为静态变量赋值为初始值,执行静态块代码。