正在阅读:深入剖析java类的构造方式深入剖析java类的构造方式

2004-08-27 10:14 出处:CSDN 作者:chensheng913 责任编辑:linjixiong

  第三块,缺省构造方法的实现,这是本文的重点,下面详细讲解。由于源代码中的缺省构造方法没有显式调用this方法,因此没有this调用(对比看看下一块的有参的构造方法的前两句),同时也没有显式的super调用,那么隐式调用父类的缺省构造方法,也就是前两条语句(主要是语句invokespecial #14 <Method Parent()>),它调用父类的构造方法,和这个类的构造相似(你可以使用javap ?c ?classpath . Parent反编译父类的字节码看看这个类的构造过程);紧接着的是执行源代码中的第一条初始化赋值语句cm2=10(即接下来的三条语句,主要是bipush 10和putfield #15 <Field int cm2>,此处回答了第一块中的疑问,即初始化赋值语句到哪儿去了。);接下来是执行cm3=cmethod()(接下来的四条语句);然后是执行初始化块中的内容System.out.println("Child's instance initialize block")(接下来的三条语句);java规范内部约定的内容至此执行完毕,开始执行构造方法的方法体中的内容,即co=new Other()(接下来的五条语句)和System.out.println("Child's default constructor")(接下来的三条语句),最后方法执行完毕返回(最后一条语句return)。

  剩下的几块相信应该不用解释了吧,有参构造方法调用无参构造方法然后执行自己的方法体,成员方法cmethod执行一条打印语句然后返回一个常量3,静态方法staticmethod执行一条打印语句。

  另外需要说明一下的是你可以将有参构造方法中的this调用去掉,然后看看反编译的结果,你会发现两个构造方法非常的类似,如果你将两个构造方法的内容改为一样的,那么反编译后的生成也将是同样的。从这个可以说明本文开始的构造顺序的说明中构造方法中this调用的判断是在编译阶段就完成的,而不是在运行阶段(说明中的意思好像是这个判断是在运行时进行的)。

  对构造过程的另一个细节你可能还不相信,就是顺序中的第二条关于非静态成员的赋予缺省初始值(内存分配部分无法考证,这是java虚拟机自动完成的),这个你可以通过在子类Child的cmethod方法的最开始用 System.out.println(cm3)打印cm3的值(输出为0,其它类型成员的值可以通过类似的方法得到)。

  下面来讲解另一个还没有解决的问题:静态成员初始化和静态初始化块的执行是在何时完成的?这个可以通过一个小小的试验推断得到:是在第一次使用该类对象时进行的(注意是类对象而不是类实例,对于类的公有静态成员可以直接通过类名进行访问,并不需要生成一个类实例,这就是一次类对象的使用而非类实例的使用,如果在生成第一个类实例前没有使用过该类对象,那么在构造第一个类实例前先完成类对象的构造(即完成静态成员初始化以及执行静态初始化块),然后再执行以上类实例的构造过程),试验的步骤如下:

  1.修改main方法,将其中的System.out.println(Child.scm1)和c= new Child(10)都注释掉(不要删除,后面还需要用到这两个语句),编译运行程序,输出将只有program start和program end,这说明没有使用类对象也没有生成类实例时不进行静态成员的构造。

  2.将System.out.println(Child.scm1)的注释取消,编译运行后输出多了父类和子类的静态初始化块部分的执行输出(使用子类的类对象将导致生成父类的类对象,父类先于子类构造)。

  3.将System.out.println(Child.scm1)注释掉并取消c= new Child(10)的注释,编译运行后输出只比最开始没有注释任何语句时少了一条(输出Child.scm1的值10)

  从以上的试验中我们可以得到前面的结论。
  本文至此可以说结束了,由于本人的java功底并不很扎实,java规范看得也不完整,因此文中可能有错误,如果您觉得某些地方有错误的话,欢迎通过mail联系。
  


察看评论详细内容 我要发表评论
作者笔名 简短内容 发表时间
:
键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品