本文不再以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. Qt 学习之路 2(22):事件总结

    Qt 学习之路 2(22):事件总结 豆子 2012年10月16日 Qt 学习之路 2 47条评论 Qt 的事件是整个 Qt 框架的核心机制之一,也比较复杂.说它复杂,更多是因为它涉及到的函数众多,而 ...

  2. nginx的使用(启动、重启、关闭)

    1. 首先利用配置文件启动nginx. 命令: nginx -c /usr/local/nginx/conf/nginx.conf 重启服务: service nginx restart 2. 快速停 ...

  3. 复习一知识点:回调函数callback

    比如我们常用的异步请求: $.ajax({ url:"test.json", type: "GET", data: {username:$("#use ...

  4. [转载]pytorch自定义数据集

    为什么要定义Datasets: PyTorch提供了一个工具函数torch.utils.data.DataLoader.通过这个类,我们在准备mini-batch的时候可以多线程并行处理,这样可以加快 ...

  5. C语言ctype.h字符函数和字符串

    ctype.h存的是与字符相关的函数: 这些函数虽然不能处理整个字符串,但是可以处理字符串中的字符: ToUpper()函数,利用toupper()函数处理字符串中的每个字符,转换成大写: Punct ...

  6. npm install 安装包报错

    D:\hapi_learn>npm .x.x npm ERR! code ENOSELF npm ERR! Refusing to install package with name " ...

  7. hdu6446 Tree and Permutation 2018ccpc网络赛 思维+dfs

    题目传送门 题目描述:给出一颗树,每条边都有权值,然后列出一个n的全排列,对于所有的全排列,比如1 2 3 4这样一个排列,要算出1到2的树上距离加2到3的树上距离加3到4的树上距离,这个和就是一个排 ...

  8. hdu-2036求任意多边形面积

    改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  9. 《高性能mysql》笔记

    组合索引和sql中的顺序有关 单列索引和sql中的顺序无关

  10. java不可见字符 trim

    trim()的作用去掉前后的空格,  但是解析excel,出现一个字符串trim之后还是有”空格“ 做了一下实验,原来一些不可见的字符不一定是“空格”, trim()也去不掉, 只能自己写方法了