静态代码块
经过学习我们知道,静态代码块是在类加载的时候执行的,那么问题就出来了,什么时候类才加载呢?其实类加载是有时机的,当同一个类加载时机多次出现时,JVM会确保每个类都只加载一次,从而静态代码块也只执行一次。
类加载的时机如下:
- 创建对象实例时
- 访问类的静态成员时(属性或方法)
- 初始化一个类的子类(会首先初始化子类的父类)
- JVM启动时,带有main方法的那个类
- 反射机制
创建对象实例
public class Demo01 {
public static void main(String[] args) {
new A();//1
new A();//2
}
}
class A{
static{
System.out.println("我是静态代码块");
}
}
以上代码运行后,可以看到语句只执行了一次,可以证明创建对象可以使类加载,而且多次创建同一个类的对象,也只能使该类加载一次。
注:使用 new 进行类加载时,静态代码块 要比 构造方法 先执行
。
访问类的静态成员
public class Demo02 {
public static void main(String[] args) {
A.fun();
A.fun();
}
}
class A{
static{
System.out.println("我是静态代码块");
}
public static void fun(){}
}
运行后,同理,结果如上面的一样。
初始化一个类的子类
public class Demo03{
public static void main(String[] args) {
new B();
}
}
class A{
static{
System.out.println("我是静态代码块A");
}
}
class B extends A{
static{
System.out.println("我是静态代码块B");
}
}
运行后,new B()时,首先调用了A的构造方法,所以 道理是一样,结果是显然的。
JVM启动带有main方法的类
public class Demo01 {
static {
System.out.println("我是带有main类中的静态代码块");
}
public static void main(String[] args) {
}
}
运行后,结果也不出所料。
总结:了解静态代码块,可以加深我们对JVM类加载的理解,让我们可以根据不同时机,静态代码块可以帮助我们在类加载时初始化一些常量之类的,便于写出符合我们需求的代码。