类怎样实例化

这种书可以扔了。。。这种问题虽然在JVM规范的层次上是有意义的问题,也是必须解决的课题,但在java语言本身的层面,一本面向学习者的书中纠结这种问题,我只能说,这本书写得一定很糟糕。现实中谁敢写这样的代码,我就一个大耳光子扇过去,你他妈睡醒没有?
■网友
"javap -v"
■网友
这个题目目是很明确的,就是要让你了解一个对象构造的过程,了解静态变量的赋值过程,子类和父类的构造顺序,这两点知识还是很重要的,在实际开发时如果不知道这些知识点,程序可能会出现重大bug。所以题目本质上没问题,问题在于题目把这些知识点混合在一起就不太好了,复杂度上升,把人看晕了,其实应该细分一下知识点的为好。。。new Test6();这句代码实际上执行的代码简单顺序是:1.初始化Object2.初始化Test53.初始化Test6其中初始化一个对象时的具体顺序是这样的:ps:父类如果还有父类就也依照此顺序先初始化父类的父类,直到Object为止。1.为父类的静态变量赋值2.执行父类的静态代码块3.为自己的静态变量赋值4.执行自己的静态代码块5.执行父类的构造代码块6.执行父类的构造方法7.执行自己的构造代码块8.执行自己的构造方法9.初始化对象完成上面的步骤其实还少了一步真正的初始化步骤:分配空间和赋上默认值,正确的顺序为以下步骤:ps:父类如果还有父类就也依照此顺序先初始化父类的父类,直到Object为止。1.用类加载器加载父类,按父类静态变量定义的顺序的为父类所有静态变量分配空间,并赋予父类静态变量默认值。2.用类加载器加载自己,按自己静态变量定义的顺序的为自己所有静态变量分配空间,并赋予自己静态变量默认值。3.按父类静态变量定义的顺序的为父类所有静态变量赋上定义的值。4.执行父类静态代码块。5.按自己静态变量定义的顺序的为自己所有静态变量赋上定义的值。6.执行自己静态代码块。7.为父类实例变量分配空间,并赋予默认值。8.为自己实例变量分配空间,并赋予默认值。9.按父类实例变量定义的顺序的为父类所有实例变量赋上定义的值。10.执行父类的构造代码块。11.执行父类的构造方法。12.按自己实例变量定义的顺序的为自己所有实例变量赋上定义的值。13.执行自己的构造代码块。14.执行自己的构造方法。15.对象构造完毕。注意:1.如果执行步骤3、5、9、12时,定义的值引入了别的类,则会初始化那个类,如果引用的类还有引用的类则也按照此顺序先初始化引用类的引用类,直到所有被引用的类全部被初始化完毕为止。2.如果一个类没有父类(Object),则它的初始化顺序可以简化成2、5、6、8、12、13、14、15。如果Test6不继承Test5,那么Object中的初始化我们不考虑,所以Test6的初始化过程可以简化成上面步骤的2、5、6、8、12、13、14、15。那么初始化时,Test6中的static int j=Test5.i这句代码是最先执行的,以下讲解Test6部不继承Test5的情况下的程序实际执行顺序:1.用类加载器加载类Test6,初始化Test6.j并为Test6.j赋默认值0。2.为Test6.j赋上定义的值Test5.i,这时候发现Test5还没有被类加载器加载,于是马上去加载Test5。3.用类加载器加载类Test5,初始化Test5.i并为Test5.i赋默认值0。4.为Test5.i赋上定义的值Test6.j,这时候发现Test6已经被类加载器加载过了,于是直接将Test6.j的值(此时Test6.j为0)赋给Test5.i,Test5.i的值从默认值0变成定义的值0。5.执行Test5静态代码块,Test5.i再次被赋值为0,Test5.i的值从定义值0变成修改后的值0。6.Test5静态变量初始化完成,静态代码块执行完毕。7.继续步骤2,为Test6.j赋上定义的值Test5.i,Test5.i此时为0,于是Test6.j被赋值为0,Test6.j的值从默认值0变成定义的值0。8.执行Test6静态代码块,Test6.j被累加,Test6.j的值从0变成1;9.Test6静态变量初始化完成,静态代码块执行完毕。10.为Test6实例变量分配空间,并赋予默认值,Test6没有实例变量,此步骤可忽略。11.为Test6所有实例变量赋上定义的值,Test6没有实例变量,此步骤可忽略。12执行Test6的构造代码块,Test6.j被累加,Test6.j的值从1变成2。13.执行Test6的构造方法,Test6没有重写构造方法,此步骤可忽略。14.对象构造完毕。最后Test5.i的值为0,Test6.j的值为2。如果Test6继承Test5,那么初始化时,Test5中的static int i=Test6.j这句代码是最先执行的,以下讲解Test6部继承Test5的情况下的程序实际执行顺序:1.用类加载器加载类Test5,初始化Test5.i并为Test5.i赋默认值0。2.用类加载器加载类Test6,初始化Test6.j并为Test6.j赋默认值0。3.为Test5.i赋上定义的值Test6.j,这时候发现Test6已经被类加载器加载过了,于是直接将Test6.j的值(此时Test6.j为0)赋给Test5.i,Test5.i的值从默认值0变成定义的值0。4.执行Test5静态代码块,Test5.i再次被赋值为0,Test5.i的值从定义值0变成修改后的值0。5.Test5静态变量初始化完成,静态代码块执行完毕。6.为Test6.j赋上定义的值Test5.i,这时候发现Test5已经被类加载器加载过了,于是直接将Test5.i的值(此时Test5.i为0)赋给Test6.j,Test6.j的值从默认值0变成定义的值0。7.执行Test6静态代码块,Test6.j被累加,Test6.j的值从0变成1;8.Test6静态变量初始化完成,静态代码块执行完毕。9.为Test5实例变量分配空间,并赋予默认值,Test5没有实例变量,此步骤可忽略。10.为Test6实例变量分配空间,并赋予默认值,Test6没有实例变量,此步骤可忽略。11.为Test5所有实例变量赋上定义的值,Test5没有实例变量,此步骤可忽略。12.执行Test5的构造代码块,Test5.i被累加,Test.i的值从0变成1。13.执行Test5的构造方法,Test5.i被累加,Test.i的值从1变成2。14.为Test6所有实例变量赋上定义的值,Test6没有实例变量,此步骤可忽略。15执行Test6的构造代码块,Test6.j被累加,Test6.j的值从1变成2。16.执行Test6的构造方法,Test6没有重写构造方法,此步骤可忽略。17.对象构造完毕。最后Test5.i的值为2,Test6.j的值为2。本答案为“免费开源”答案,您完全可以一字不留的copy走。


推荐阅读