看到有一本书中说,(当一个类里只有非静态变量)非静态变量先分配内存空间,此时它的值
是null,赋值的语句会提取到构造函数中执行。
那么,一个类里有静态变量,静态代码块,非静态变量,非静态代码块和构造函数时,按照
分配内存空间和赋值两个过程,初始化的过程究竟是怎样的呢?
1.项目启动时,静态变量首先被分配内存地址,并有一个变量名指向这一个地址 static a= xxx;然后加载静态方法。全都只加载一次。并且不会被GC
非静态变量或方法 使用对象的时候才会被调用。那对象就是由构造方法new出来的。你不new这个对象构造方法就不会使用。
2.简单测试类。
public class TestNew {
static int a = 3;
static int b;
static void meth(int x){
System.out.println("x = "+x);
System.out.println("a = "+a);
System.out.println("b = "+b);
}
static {
System.out.println("static block initialized");
b = a*4;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
meth(42);
}
}
结果:static block initialized
x = 42
a = 3
b = 12
Java是采用懒加载的策略的,就是什么时候用到,什么时候加载。说简单点就是:
1、从硬盘中找到xxx.class 然后载入内存。
2、进行初始化,就是静态变量什么的。
3、使用。
比如说你随便写个类,然后你debug看看就知道了。
比如说,首先执行main方法时候,发现用到了CarFlowTest这个类,于是就把class加载到内存,然后初始化。
将java源文件编译成class的时候,会自动添加两个方法,一个是 这个方法里面用于static的初始化。
只有载入内存的时候用到了一次。然后F5点一下
你发现这个时候才到第12行,还没有new 呢。F6在点一下
你发现调用了这个方法了。就是准备哪些非静态变量的。
所以class中有两个自动添加的方法,初始化static修饰的。只有载入内存初始化时调用一次。
方法,new 的时候调用,每创建一个对象调用一次。
你把所有的都写上,static 变量,代码块什么的。自己打断点看下就知道了。
在首次创建类对象,或者首次访问类的静态方法或静态变量时,类加载器会自动加载该类,类加载器(ClassLoader)装载一个类的大致流程:
1. 类加载
取得类的二进制流,转为方法区中的数据结构,在Java堆中生成相应的java.lang.Class对象
2. 链接
验证:保证Class流的格式是正确的
准备:在方法区中分配内存,并为类设置初始值,此时static final常量会被初始化为定义值,其他变量(静态和非静态)都会置为默认值(数字为0,引用为null)
解析:符号引用替换为直接引用
3. 初始化
执行类构造器,此时static变量赋值为字段定义处的初始值(初始化一次),static{}会被执行一次。
用new创建对象时,对象所有非静态变量都设置为默认值,然后执行字段定义处的初始化动作,最后执行构造方法。