`
leon.s.kennedy
  • 浏览: 107294 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

探究Java初始化的过程

 
阅读更多

最近又在翻《thinking in java》,这本书,怎么说呢,以前学java的时候,老师就没有把它作为教材,但是我偏偏只买了这本书,一直收获很大。好了,言归正传,结合自己的偶然遇到的一个在构造函数中调多态方法引起的思考,讲述一下java的初始化到底是怎样的一个过程。

所谓初始化,当然也就指的是变量。变量可以是内置的变量或者我们创建的类的对象。

有人说,本来初始化本来就是一件很简单的事情,的确,但是java作为一门面向对象语言,由于具有继承、多态,静态、动态绑定等多种特性,所以其初始化的情景可谓是五花八门。现在就一步一步的分析其初始化过程。下面就是几个小原则。优先级依次递减。

1、静态块优先

程序首先会执行静态块的内容,这也就有了不写main方法就跑hello world的小故事,相信说到这里,大家就有了思路。我们都知道静态类型是和类绑定的而不是和具体实例对象绑定。也就是说,引用一个静态变量的方式往往是MyClass.xxx.这个特点决定了其在编译的阶段就已经分配好了固定的空间。

2、父类优先

由于继承的特性,当导出类(子类)的对象被创建的时候,程序将向上追溯到最初的父类,执行其初始化的操作。然后一次向下调用子类的构造函数。按照这个思路,那么每一个实例第一个要初始化的必定是Object类了。

3、成员变量优先

一定要注意,成员变量按照其声明的顺序会被初始化,并且立刻被初始化为二进制的0,这个动作发生在所有事件之前,也就是编译器会立刻将分配给对象的空间初始化。一会的小例子将证明这一点。

最后就是调用类的构造方法了。

下面有一个不错的例子,为了演示成员变量最早被初始化为0了,我们将在父类的构造函数中调用子类的方法(利用了多态)。

  1. package fruit;  
  2.    
  3.  import vege.Inner;  
  4.    
  5.    
  6.   
  7.  public class Fruit {  
  8.      //static block  
  9.      static {  
  10.          System.out.println("In Fruit static");  
  11.      }  
  12.        
  13.      private Inner i = new Inner(); //a private member  
  14.      public Fruit(){  
  15.          System.out.println("Before Fruit Constructor");  
  16.          show();  //由于多态的特性,此处子类Apple覆写的方法会被调用  
  17.          System.out.println("After Fruit Constructor");  
  18.      }  
  19.      public void show(){  
  20.          System.out.println("show:Fruit.");  
  21.      }  
  22.        
  23.      public static void main(String[] args) {  
  24.          // TODO code application logic here  
  25.          new Apple(3);  
  26.      }  
  27.           
  28.  } 

现在父类中须要初始化的有

  • 静态块
  • 一个Inner类私有成员
  • 构造函数

现在我们看子类的代码

  1. package fruit;  
  2.    
  3.  public class Apple extends Fruit{  
  4.     //静态块  
  5.      static{  
  6.          System.out.println("In Apple static");  
  7.      }  
  8.      private int weight = 1//初始化为1 注意区别这里和 初始化为0  
  9.        
  10.      public Apple(int para_weight){  
  11.          System.out.println("Before Apple Constructer: weight = "+weight);  
  12.          weight = para_weight;  
  13.          System.out.println("Apple Constructor: weight="+weight);  
  14.      }  
  15.        
  16.      @Override 
  17.      public void show(){  
  18.          System.out.println("show apple: weight =" + weight);  
  19.      }  
  20.        
  21.  } 
子类须要初始化的有
  • 静态块
  • 私有成员weight
  • 构造函数

那么当我们运行的时候会有怎样的结果呢?猜想。。。。。

下面就是执行的结果:

 

Look! 首先执行父类的静态块,之后是子类的静态块,这两个应该没有什么问题。接下来就是对父类成员变量的初始化了。首先是父类的私有成员Inner对象,打印了一条“ Inner Constructor”。

接下来就是父类的构造函数,可见由于java的多态性,Fruit的构造方法调用了其子类Apple的show方法,并且我们可以清晰的看到,此刻Apple类中weight变量的值是0!说明,类的成员变量无论是否赋值,在各种初始化之前早已被设置为二进制0了。

于是乎我想起了很多关于java的书都在说。。“如果类的私有变量没有赋值,就会被设置为0”。。这句话显然把时间弄混了。。。应该是编译器早已初始化了私有变量,均为0,之后才会执行到赋值语句。

父类的构造函数结束之后,再次回到子类,初始化私有变量(也就是我们常说的赋值语句,因为初始为0的工作早做完了)。所以我们才会看到“Before Apple Constructor weight = 1”,执行完构造函数后,我们就看到了weight终于变成了我们创建对象是传进的3了,呼,初始化结束。

总  结

那么总结一下就是这样的:

  1. 编译器初始化所有的已分配的空间为二进制0  (这是我们的私有变量都会为0,刚才的例子)
  2. 执行父类静态代码 执行子类静态代码
  3. 初始化父类成员变量(我们常说的赋值语句)
  4. 初始化父类构造函数
  5. 初始化子类成员变量
  6. 初始化子类构造函数

原文链接:http://www.cnblogs.com/octobershiner/archive/2012/03/12/2391899.html

分享到:
评论

相关推荐

    探究java的ClassLoader及类变量初始化顺序

    NULL 博文链接:https://crazybackkom.iteye.com/blog/968174

    java web的运行开发环境和servlet的开发部署

    其中,JDK 是 Java 开发的基础环境,而 Tomcat 是一个 Servlet 和 JSP 容器,负责管理 Servlet 和 JSP 的初始化、运行和销毁等。 Servlet 是 Java 服务器端小程序,用来进行 web 开发,接收 HTTP 请求,产生静态的 ...

    Java思维导图xmind文件+导出图片

    理解通信协议传输过程中的序列化和反序列化机制 基于框架的RPC通信技术 WebService/ApacheCXF RMI/Spring RMI Hession 传统RPC技术在大型分布式架构下面临的问题 分布式架构下的RPC解决方案 Zookeeper ...

    基于Java面向对象程序设计课程报告.doc.doc

    游戏主要实现了游戏场景的构造,坦克及子弹类的初始化,敌我坦克对战,游戏存盘及 读档等功能。关键词: Java; 面向对象; 敌我坦克对战; 引言坦克大战是一个经典的单机对战游戏,其在青少年中非常流行,目前游戏...

    【Java设计模式】你对单例模式了解多少,一文深入探究

    目录单例模式懒汉式单例模式未初始化问题解决Double Check 双重检查方案一:不让第二步和第三步重排序-DoubleCheck方案二:基于类初始化-静态内部类饿汉式饿汉式与懒汉式最大区别序列化破坏单例模式原理枚举单例基于...

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    第92节类加载的过程-初始化00:19:41分钟 | 第93节类加载器00:22:41分钟 | 第94节双亲委派模型00:17:03分钟 | 第95节运行时栈帧结构00:08:46分钟 | 第96节局部变量表00:20:48分钟 | 第97节操作数栈00:08:36分钟 ...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    市场上相应的检测平台诸如检测通、凡特网等皆为pc端检测网站,并且操作繁琐不够人性化,用户在实地使用中存在很多问题。昆山工业技术研究院着眼于为委托用户和质检机构搭建良好的沟通桥梁,免去目前市场业务中企业...

    深入理解JVM内存结构及运行原理全套视频加资料.txt

     第92讲 类加载的过程-初始化 00:19:41  第93讲 类加载器 00:22:41  第94讲 双亲委派模型 00:17:03  第95讲 运行时栈帧结构 00:08:46  第96讲 局部变量表 00:20:48  第97讲 操作数栈 00:08:36  第98讲...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第二阶段47讲、ClassLoader初始化阶段详细介绍clinit.mp4 │ 高并发编程第二阶段48讲、JVM内置三大类加载器的详细介绍.mp4 │ 高并发编程第二阶段49讲、自定义类加载器ClassLoader顺便问候了一下...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第二阶段47讲、ClassLoader初始化阶段详细介绍clinit.mp4 │ 高并发编程第二阶段48讲、JVM内置三大类加载器的详细介绍.mp4 │ 高并发编程第二阶段49讲、自定义类加载器ClassLoader顺便问候了一下...

    Activiti6.0教程例子下载

    Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于 Java 的超快速、超稳定的 BPMN2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更加强调面向业务人员。 Activiti 流程引擎...

Global site tag (gtag.js) - Google Analytics