知识大全 逐步深入剖析java类的构造方式

Posted 指令

篇首语:聪明出于勤奋,天才在于积累本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 逐步深入剖析java类的构造方式相关的知识,希望对你有一定的参考价值。

  概要 本文通过查看一个精心构造的类结构的运行输出和使用javap工具查看实际生成的java字节码(bytecode)向java程序员展示了一个类在运行时是如何构造生成的      关键字 java 构造 javap 字节码 bytecode  按照java规范 一个类实例的构造过程是遵循以下顺序的      如果构造方法(constructor 也有翻译为构造器和构造函数的)是有参数的则进行参数绑定      内存分配将非静态成员赋予初始值(原始类型的成员的值为规定值 例如int型为 float型为 f boolean型为false 对象类型的初始值为null) 静态成员是属于类对象而非类实例 所以类实例的生成不进行静态成员的构造或者初始化 后面将讲述静态成员的生成时间      如果构造方法中存在this()调用(可以是其它带参数的this()调用)则执行之 执行完毕后进入第 步继续执行 如果没有this调用则进行下一步      执行显式的super()调用(可以是其它带参数的super()调用)或者隐式的super()调用(缺省构造方法) 此步骤又进入一个父类的构造过程并一直上推至Object对象的构造      执行类申明中的成员赋值和初始化块      执行构造方法中的其它语句     现在来看看精心构造的一个实例     class Parent    int pm ;  int pm = ;  int pm =pmethod();    System out println( Parent s instance initialize block );    public static int spm = ;  static    System out println( Parent s static initialize block );      Parent()    System out println( Parent s default constructor );    static void staticmethod()    System out println( Parent s staticmethod );    int pmethod()    System out println( Parent s method );  return ;        class Child extends Parent    int cm ;  int cm = ;  int cm =cmethod();  Other co;  public static int scm = ;    System out println( Child s instance initialize block );    static    System out println( Child s static initialize block );      Child()    co=new Other();  System out println( Child s default constructor );    Child(int m)    this();  cm =m;  System out println( Child s self define constructor );    static void staticmethod()    System out println( Child s staticmethod );      int cmethod()    System out println( Child s method );  return ;          class Other    int om ;  Other()   System out println( Other s default constructor );        public class InitializationTest    public static void main(String args[])    Child c;  System out println( program start );  System out println(Child scm );  c= new Child( );  System out println( program end );        进入此文件所在的目录 然后  编译此文件 javac InitializationTest java  运行此程序 java ?classpath InitializationTest  得到的结果是     program start  Parent s static initialize block  Child s static initialize block     Parent s method  Parent s instance initialize block  Parent s default constructor  Child s method  Child s instance initialize block  Other s default constructor  Child s default constructor  Child s self define constructor  program end    如果没有看过上面的关于类的构造的说明 很容易让人误解为类的构造顺序是如下的结果(忽略参数绑定 内存分配和非静态成员的缺省值赋值)      完成父类的非静态成员初始化赋值以及执行初始化块(这个的先后顺序取决于源文件中的书写顺序 可以将初始化块置于成员声明前 那么先执行的将是初始化块 将上面的代码稍稍变动一下就可以验证这一点 )     调用父类的构造方法完成父类构造      完成非静态成员的初始化赋值以及执行初始化块      调用构造方法完成对象的构造 执行构造方法体中的其它内容     如果根据以上java规范中给出的顺序也可以合理的解释程序的输出结果 那么如何亲眼看到是规范中的顺序而不是以上根据程序的输出推断的顺序呢?  下面就使用JDK自带的javap工具看看实际的顺序 这个工具是一个根据编译后的字节码生成一份字节码的助记符格式的文档的工具 就像根据机器码生成汇编代码那样   反编译 javap c classpath Child  输出的结果是(已经经过标记 交替使用黑体和斜体表示要讲解的每一块)     Compiled from InitializationTest java  class Child extends Parent   int cm ;  int cm ;  int cm ;  Other co;  public static int scm ;  static ;  Child();  Child(int);  int cmethod();  static void staticmethod();      Method static    bipush    putstatic #    getstatic #    ldc #    invokevirtual #    return    Method Child()   aload_    invokespecial #    aload_    bipush    putfield #    aload_    aload_    invokevirtual #    putfield #    getstatic #    ldc #    invokevirtual #    aload_    new #    dup   invokespecial #    putfield #    getstatic #    ldc #    invokevirtual #    return    Method Child(int)   aload_    invokespecial #    aload_    iload_    putfield #    getstatic #    ldc #    invokevirtual #    return    Method int cmethod()   getstatic #    ldc #    invokevirtual #    iconst_    ireturn    Method void staticmethod()   getstatic #    ldc #    invokevirtual #    return    请仔细浏览一下这个输出并和源代码比较一下     下面解释如何根据这个输出得到类实例的实际的构造顺序 在开始说明前先解释一下输出的语句的格式 语句中最前面的一个数字是指令的偏移值 这个我们在此可以不管 第二项是指令助记符 可以从字面上大致看出指令的意思     例如 getstatic 指令将一个静态成员压入一个称为操作数堆栈(后续的指令就可以引用这个数据结构中的成员)的数据结构 而 invokevirtual 指令是调用java虚拟机方法 第三项是操作数(#号后面跟一个数字 实际上是类的成员的标记) 有些指令没有这一项 因为有些指令如同汇编指令中的某些指令一样是不需要操作数的(可能是操作数是隐含的或者根本就不需要) 这是java中的一个特色     如果你直接检查字节码 你会看到成员信息没有直接嵌入指令而是像所有由java类使用的常量那样存储在一个共享池中 将成员信息存储在一个常量池中可以减小字节码指令的大小 因为指令只需要存储常量池中的一个索引而不是整个常量     需要说明的是常量池中的项目的顺序是和编译器相关的 因此在你的环境中看到的可能和我上面给出的输出不完全一样 第四项是对前面的操作数的说明 实际的字节码中也是没有的 根据这个你能很清楚的得到实际上使用的是哪个成员或者调用的是哪个方法 这也是javap为我们提供的便利     说完上面这些你现在应该很容易看懂上面的结果和下面将要叙述的 cha138/Article/program/Java/hx/201311/25958

相关参考

知识大全 浅谈JAVA中类的构造器

浅谈JAVA中类的构造器  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  现在越来越多的人开始学习

知识大全 构造和析构成员函数

    类有一个特殊的成员函数叫做构造成员函数它通常用于初始化类的数据成员在创建对象时会自动调用类的构造成员函数Java中的构造成员函数必须与该类具有相同的名字另外构造成员函数一般都应用public类

知识大全 彻底剖析C# 2.0泛型类的创建和使用

彻底剖析C#2.0泛型类的创建和使用  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!lishixin

知识大全 Oracle数据块原理深入剖析

Oracle数据块原理深入剖析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  数据块(Oracl

知识大全 深入剖析Asp.net资源文件

深入剖析Asp.net资源文件  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一资源文件的定义 

知识大全 使命必达: 深入剖析WCF的可靠会话

使命必达:深入剖析WCF的可靠会话  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  整个可靠会话的

知识大全 自动内存管理机制深入剖析-C#分析篇

自动内存管理机制深入剖析-C#分析篇  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在NETFr

知识大全 VS2005数据存取层深入剖析基础篇

VS2005数据存取层深入剖析基础篇  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!摘要本文试图对V

知识大全 VS2005数据存取层深入剖析高级篇

VS2005数据存取层深入剖析高级篇  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!一扩展表格适配器

知识大全 面试问题深入剖析(4)

10.你和同事们怎样相处?分析通过这个问题以及前面上下级关系和朋友关系的问题,面试人可以对求职者的有效沟通技能得出一个总体印象。从某种意义上说,如何和同事们相处是最关键的沟通问题,因为根据美国劳工部的