在java中,一个类被使用要经过装载,连接,初始化这样的过程
一、装载:
类装载器(Bootstrap ClassLoader 或者用户自定义的ClassLoader) 把编译形成的class文件载入内存,创建类相关的Class对象,这个Class对象封装了我们要使用的类的类型信息。
二、连接
连接阶段又可以分为三个子步骤:验证、准备和解析。
(1)验证就是要确保java类型数据格式 的正确性,并适于JVM使用
(2)准备阶段,JVM为静态变量分配内存空间,并设置默认值,注意,这里是设置默认值,比如说int型的变量会被赋予默认值0 。在这个阶段,JVM可能还会为一些数据结构分配内存,目的 是提高运行程序的性能,比如说方法表
(3)解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用。这个阶段可以被推迟到初始化之后,当程序运行的过程中真正使用某个符号引用的时候 再去解析它
三、初始化
类会在首次被“主动使用”时执行初始化,为类(静态)变量赋予正确的初始值。在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化块给出的。而我们这里所说的主动使用 包括: 创建类的实例、调用类的静态方法、使用类的非常量静态字段、调用JavaAPI中的某些反射方法、 初始化某个类的子类、 含有main()方法的类启动时
初始化一个类包括两个步骤:
(1) 如果类存在直接父类的话,且直接父类还没有被初始化,则先初始化其直接父类
(2) 如果类存在一个初始化方法,就执行此方法注:初始化接口并不需要初始化它的父接口。
以上就是java中的类初始化
我所见到的调用顺序:
main函数,调用类A,A继承Abase
1、main函数所在类的静态代码块或者静态成员的初始化
2、main函数调用
3、main中用到类A的基类Abase中,静态代码块或者静态成员的初始化
4、类A的静态代码块或者静态成员的初始化 (<cinit>函数)
5、Abase的构造函数调用
6、A的构造函数调用,此时实际上在class文件中会把类中的非静态成员变量和非静态代码块加入到已有的构造函数代码之前,形成一个最终的构造函数,非静态成员变量和非静态代码块的执行顺序跟代码的书写顺序一致 !<init>
比如
```
class A{
int a = 0;//1
{
a = 1;//2
}
public A(){
a = 2;//3
}
}
```
那么构造类A的时候调用顺序是1-2-3
也就是说要注意此时成员变量的初始化都是在调用构造函数所在的线程中执行的!
7、最后是使用到的方法调用
参考链接:http://blog.csdn.net/moreevan/article/details/6968718
http://www.cnblogs.com/zlingh/p/4040567.html
网友评论