前言
笔者前些时候在写代码的时候,需要本地缓存,在类加载的时候必须初始化并在程序运行中不会被GC回收。于是笔者想到使用静态变量与静态代码块。那么静态代码块与普通代码块的区别呢,它在何时运行?
1. 示例代码
public class Man {
private static String name;
private String addr;
static {
name = "man";
}
{
name = "all";
addr = "xxx";
}
public Man(String addr) {
this.addr = addr;
}
public static void main(String[] args) {
Man man = new Man("HK");
}
}
我们知道,static是在类加载的时候加载,所有类共同使用,存储与方法区(meta区),因此,static变量不能使用默认的序列化方式。
2. 加载顺序分析
2.1 通过我们的分析,应该static代码块优先加载,
调试结果一致
那么接下来呢
加载了类后,加载了new 构造,然后加载非静态代码块
最后加载构造函数
过程结束了。但是如果多个对象呢,static与非static代码块是否需要多次加载,分析static是类加载时候加载,肯定不会;那么非static呢?
3. 多对象分析
public class Man {
private static String name;
private String addr;
static {
name = "man";
}
{
name = "all";
addr = "xxx";
}
public Man(){
System.out.println("-----------------");
}
public Man(String addr) {
this.addr = addr;
}
public static void main(String[] args) {
Man man = new Man("HK");
Man man1 = new Man("HK");
}
}
1)static代码块
2)new关键字
3)非静态代码块
4)构造函数
5)new其他对象
6)非静态代码块(再次加载)
7)构造函数
4. 对象如何取变量
调试对象的变量结果如下
仅能获取非静态变量
如果要获取静态变量,需要使用类名.属性
5. 总结
此问题的关键在于需要熟悉JVM的JMM模型, 知道类的加载过程,对象的创建生命周期。
static仅在类加载的时候加载一次
非static每次new 对象就要加载一次,加载顺序在构造函数之前