读书人

JAVA种的初始化过程

发布时间: 2012-09-22 21:54:54 作者: rapoo

JAVA类的初始化过程
1、java类中的字段,第一步是自动初始化,比如定义了

private int i;

由于没有给其赋值,i会被自动赋值为0。这个步骤是仅限于类中的字段的,如果方法中的临时变量,不会有这个动作。而且如果在方法中使用未经赋值的变量,编译会不通过

2、第二步是指定初始化
private int i = 3;

如果有了显式的赋初值,那么第一步的自动初始化就不会发生了。但是该步骤和自动初始化,必定发生其一。即使在构造方法里给i赋值为4,还是首先会调用指定初始化,先赋值成3再赋值成4

3、第三步是初始化语句块初始化
{    i = 4;}

这个动作发生在自动初始化或者指定初始化之后,发生在构造方法初始化之前。如果没有初始化语句块,那么这个步骤就不会发生

4、第四步才是构造方法中的初始化
public className(){    i = 4;}

这个动作是发生在初始化语句块之后,如果没有的话,就是发生在自动初始化或者指定初始化之后。这个动作也是初始化的最后一个步骤

5、在类中的任何方法执行之前(包括构造方法),首先会完成所有字段的初始化

6、类只在初次使用时才会被加载。“初次使用”通常是指创建类的第一个对象时,或者当初次访问类中的static字段或者static方法时。但是由于构造方法实际上也是static方法(只是static关键字没有要求显式地写出来),所以也可以说,类的加载是发生在类的任何static成员(包括static字段、static方法、构造方法)被初次访问时

7、当初始化类的字段时,会先初始化static字段,再初始化非static字段

8、在调用构造方法时,会从最顶端的基类开始,依次调用每个类的构造方法。如果基类的构造方法是默认构造方法(不含构造方法参数),那么就不需要显式地调用super(),但是如果基类只包含含参数的构造方法,就必须显式地调用super() 1 楼 木mu 2012-01-05 “初次使用”通常是指创建类的第一个对象时,或者当初次访问类中的static字段或者static方法时。但是由于构造方法实际上也是static方法(只是static关键字没有要求显式地写出来),所以也可以说,类的加载是发生在类的任何static成员(包括 static字段、static方法、构造方法)被初次访问时

“初次使用通常是指创建类的第一个对象时,或者当初次访问类中的static字段或者static方法时”,
前半句木有问题,可是后半句就不对了吧?当JVM 中存在一个某个对象的实例,一定是通过new 关键字显示调用了该对象的构造方法才会存在该对象的实例,即便是用反射最后也是调用目标对象的构造器来进行实例化的。而在木有实例化该对象的情况下访问对象中的static 字段或者static 方法时,JVM中不存在该对象的实例的。
还有 “但是由于构造方法实际上也是static方法” ,这个观点貌似也不正确吧?其实就是楼主这个观点导致上面的结论。
static 跟类的构造器是两回事,构造器根本不等于static 的方法!想想看,我们通过new 关键字可以无限量的创建某个类的实例,可是我们调用该类中某个static 类型的方法或者字段,可是别忘了JavaSE 规范中提到的static 类型的变量或者方法JVM 仅会存在一份并且是全局唯一,跟“构造方法实际上也是static方法”是不是矛盾了?
而且,从类的加载顺序来看,两者也不等同,static 修饰的变量或者方法都是由JVM 自动加载并且初始化,而此时JVM 中并不存在该对象的任何实例,而成员变量必须是我们显示的通过new 关键字调用构造器之后才会触发JVM 去逐一加载并初始化。
以上是个人观点,也是通过一点简单的代码做的实验以及参考的一些资料所得出的结论,有不对的地方,还请指正。
2 楼 kyfxbl 2012-01-05 还有 “但是由于构造方法实际上也是static方法”,这个观点貌似也不正确吧?


LZ你好,谢谢你的热情回帖。貌似你的回帖比我的主贴还长了,呵呵

这个观点是《thinking in java》里提出来的,我没有验证过,只是觉得他也说得通,就记下来了。也许不一定是正确的,谢谢哦 3 楼 木mu 2012-01-17 恩,书上的东西,有些真的是有问题,虽然 <Thinking in java> 是业内的权威书籍,可是难免会有错误,你说呢?
我觉得吧,相信编译器绝对没错,比谁都靠谱!

读书人网 >编程

热点推荐