本文不再以ClassLoader的视角解释这些问题。

首先,Java代码有个特点,就是成员变量可以在前面的方法中使用,在后面定义。这一特性,很多人说Java了不起,可是为什么呢?Java为何能够这样呢?

我们首先来看一道面试题:

写出上面代码的运行结果。
其实对于Java了解比较深入的人,不屑于解决这道题,因为看代码写运行结果,再常规不过,可是这个题,要是写准了,还真的不容易,因为,我们要以类似C语言的视角审视这道题。
OK,我们首先理解一个基本概念,内存空间一定是先申请,再初始化,再使用的。例如C语言中的malloc分配空间,然后初始化写0,然后使用。其实Java也是如此的。
首先,我们从main方法入手,只有一行new对象(第26行)。
new对象首先要加载类,这是肯定的了,因此“Test”需要加载类,也就是加载Test的字节码文件到方法区(永久代)中。这时需要把类中的“static”部分处理完成。
也就是说,static部分是随着Test的字节码文件进入到永久代的。
它的过程是:先把所有的static部分申请空间,然后再给每一个static成员由上至下分配初始值。初始值有两种,一种是Java对于基本数据类型的默认初始值,这个默认初始值在申请空间之时就给每一个成员赋予了,另一种是Java程序员利用“=”对成员进行赋初始值。
如图所示,五个静态成员在永久代首先被分配内存。
此时,k=0,t1=null,t2=null,i=0,n=0。空间申请完成之后,我们把0赋值给k,虽然k被分配内存之后就是0,但是依然还要把0再赋值给k,因为“=”右边的“0”是程序员对k的赋值。然后是给t1实例一个对象,也就是t1原本是null,现在把new出来的对象赋值给t1,于是就要构建一个Test对象。构建对象时,要把所有的非static部分初始化一份,放入堆内存。
这时,你就理解了Java语法中,为什么静态成员是“类名.成员”,而非静态成员是“对象.成员”了。因为所属关系不同。
那么我们开始找非静态的成员
如图,有j和一个构造块。
因此是先给j申请空间,然后运行print("j")方法,把方法的返回值交给j。
于是,这个程序的第一段打印结果出来了:
打印:
此后,k=1 , n=1 , i=1。
然后是接着找非静态的部分,就只有构造块了,因此是:
此后,k=2 , n=2 , i=2。
这时,我们构造对象的准备工作做完了,也就是非静态的代码都执行完了,因此开始实例化对象,Java实例化对象使用构造方法,因此执行:
打印:
此后,t1不再是null,然后初始化t2,过程和t1一样,因此运行结果是:
再然后初始化静态的i,因此是执行:
输出打印:
然后初始化 n(第6行),直接把n赋值为99。但是什么都不打印。
然后再往下是静态块:
输出打印:
至此,所有的静态部分也都初始化完毕了,可以new Test("init")了:
输出打印:
所以总体打印如下:
总结,其实Java本身也是代码从上往下走的,只不过静态部分和非静态部分在两个次元里。Java的成员有分配空间,赋默认值两个过程,且首先为全体成员申请空间,然后由上至下逐一赋值。

Java类与对象初始化的过程(一道经典的面试题)的更多相关文章

  1. Java类和对象初始化

    类的生命周期: Java类的初始化: 本阶段负责为类变量赋正确的初始值.(类变量即静态变量) Java编译器把所有的类变量初始化语句和静态初始化器通通收集到<clinit>方法中,该方法只 ...

  2. Java中子类对象初始化的过程

    Java中的继承机制看似简单,实际上包含了很多细节.最近在刷题过程中屡屡跳坑,于是自己仔细再学习了一下Java中子类初始化的细节,与大家分享. class Father { Father(){}; } ...

  3. 解析Java类和对象的初始化过程

    类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...

  4. [转载]解析 Java 类和对象的初始化过程

    原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-clobj-init/index.html 由一个单态模式引出的问题谈起 类的初始化和对象初始化 ...

  5. JAVA 对象初始化的过程

    对象初始化的过程例:Student S    =    new Student();1.因为new Student()用到了Student类,所以会把它从硬盘上加载进入内存2.如果有static静态代 ...

  6. [Java初探08]__简单学习Java类和对象

    前言 在前面的学习中,我们对面向对象的编程思想有了一个基本的了解,并且简单的了解了类和对象的定义.那么类和对象在Java语言中是如何表现的,这次,就从实际出发,学习一下一下类和对象在Java语言中的使 ...

  7. java类的成员初始化顺序和初始化块知识

    java类的成员初始化顺序和初始化块知识 转自:http://blog.csdn.net/lgfeng218/article/details/7606735 属性.方法.构造方法和自由块都是类中的成员 ...

  8. Java 类成员的初始化顺序

    Java 类成员的初始化顺序 前言:开发中碰到一个Java文件中有很多的成员变量,包括静态和非静态的,还有很多的初始化方法,很好奇这些成员的初始化顺序,在这里作个研究.   1  无继承情况下的Jav ...

  9. java类和对象之间的差

    java类和对象之间的差别是一个普遍的问题,刚开始学习java当它来到与类和对象接触.今天就来总结一下它们之间的差异. 先说说class和object差异.事实上,词:object是全部class的父 ...

随机推荐

  1. CSS基础(续)

      老男孩第39天 老男孩 CSS  CSS的常用属性 4 文本属性 font-size: 10px; text-align: center; 横向排列 line-height: 200px; 文本行 ...

  2. Java StringBuffer

    String是不变类,用String修改字符串会新建一个String对象,如果频繁的修改,将会产生很多的String对象,开销很大.因此java提供了一个StringBuffer类,这个类在修改字符串 ...

  3. bootstrap多选框

    不多说,先上图片 本多选框是用的bootstrap的样式为基础,将弹出框css改造,然后自己写的js得到. 下面为全部页面的代码,需要的可以自己改动js,得到自己需要的效果 <!DOCTYPE ...

  4. Dev Express Report 学习总结(六)Dev Express Reports自定义Summary

    在我们使用DevExpress开发报表的过程中,对于页面中复杂的数据合计,我们可能会使用到自定义Summary.下面通过一个例子来进行说明: 首先,我建立了如上图所示的报表页面,其中的数据源来自cla ...

  5. 谨慎使用多线程中的fork 学习!!!!

    前言 在单核时代,大家所编写的程序都是单进程/单线程程序.随着计算机硬件技术的发展,进入了多核时代后,为了降低响应时间,重复充分利用多核cpu的资源,使用多进程编程的手段逐渐被人们接受和掌握.然而因为 ...

  6. jquery dataTable 自定义 Button及按钮事件

    参考网址:http://stackoverflow.com/questions/18134913/jquery-datatabletabletool-custom-buttons-calling-ev ...

  7. 前台js escape及后台C# Server.UrlEncode 对QueryString传参的含~!@#$%^&*等特殊字符的处理

    通常情况下,我们在List列表页面,会包含Create,Edit,Delete等操作按钮, 而通常的处理是: Create按钮跳转到DataCreate.aspx Edit按钮跳转到DataEdit. ...

  8. C++计算二叉树的节点数和高度

    用struct结构体的写法: /* * description: 计算二叉树的层数和节点数 * writeby: nick * date: 2012-10-23 16:16 * */ #include ...

  9. Murano Weekly Meeting 2016.06.21

    Meeting time: 2016.June.21 1:00~2:00 Chairperson:  Kirill Zaitsev, from Mirantis Meeting summary: 1. ...

  10. static 和 final 和 static final

    众所周知,static 是静态修饰关键字:可以修饰变量,程序块,方法,类. 1.修饰变量. 得知:如果static修饰的是变量,则JVM会将将其分配在内存堆上,该变量就与对象无关,所有对该变量的引用都 ...