Java类、实例的初始化顺序
今晚是阿里巴巴 2013 校园招聘的杭州站笔试。下午匆忙看了两张历年试卷,去现场打了瓶酱油。
题目总体考察点偏基础,倒数第二题(Java 附加题)比较有趣,考察了 Java 初始化机制的细节,在此摘录出来。
题目
求如下 java 代码的输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
分析
代码主要考察的是类、变量初始化的顺序。
一般的,我们很清楚类需要在被实例化之前初始化,而对象的初始化则是运行构造方法中的代码。
本题的代码显然没有这么简单了。本题中涉及到了static {…}
和 {…}
这种形式的代码块,以及在类的静态变量中初始化该类的对象这种交错的逻辑,容易让人焦躁(类似于密集恐惧症吧=()。实际上,按照类的装载、链接和初始化逻辑,以及对象初始化的顺序来思考,不难得到答案。
代码组成
成员变量 2~6 行的变量是 static 的,为类 T 的静态成员变量,需要在类加载的过程中被执行初始化;第 8 行的
int j
则为实例成员变量,只再类被实例化的过程中初始化。代码段 9~11 行为实例化的代码段,在类被实例化的过程中执行;13~15 行为静态的代码段,在类被加载、初始化的过程中执行。
方法 方法
public static int print(String str)
为静态方法,其实现中牵涉到 k,i,n 三个静态成员变量,实际上,这个方法是专门用来标记执行顺序的方法;T 的构造方法是个实例化方法,在 T 被实例化时调用。main 方法 main 方法中实例化了一个 T 的实例。
执行顺序分析
在一个对象被使用之前,需要经历的过程有:类的装载 -> 链接(验证 -> 准备 -> 解析) -> 初始化 -> 对象实例化。(详情参见《Java 类的装载、链接和初始化》),这里需要注意的点主要有:
在类链接之后,类初始化之前,实际上类已经可以被实例化了。
就如此题代码中所述,在众多静态成员变量被初始化完成之前,已经有两个实例的初始化了。实际上,此时对类的实例化,除了无法正常使用类的静态承运变量以外(还没有保证完全被初始化),JVM 中已经加载了类的内存结构布局,只是没有执行初始化的过程。比如第 3 行
public static T t1 = new T("t1");
,在链接过程中,JVM 中已经存在了一个 t1,它的值为 null,还没有执行new T("t1")
。又比如第 5 行的public static int i = print("i");
,在没有执行初始化时,i 的值为 0,同理 n 在初始化前值也为 0.先执行成员变量自身初始化,后执行
static {…}
、{…}
代码块中的内容。如此策略的意义在于让代码块能处理成员变量相关的逻辑。如果不使用这种策略,而是相反先执行代码块,那么在执行代码块的过程中,成员变量并没有意义,代码块的执行也是多余。
类实例化的过程中,先执行隐式的构造代码,再执行构造方法中的代码 这里隐式的构造代码包括了
{}
代码块中的代码,以及实例成员变量声明中的初始化代码,以及父类的对应的代码(还好本题中没有考察到父类这一继承关系,否则更复杂;))。为何不是先执行显示的构造方法中的代码,再执行隐式的代码呢?这也很容易解释:构造方法中可能就需要使用到实例成员变量,而这时候,我们是期待实例变量能正常使用的。
有了如上的分析,也就能推到出最终的输出结果了。实际上,这几个原则都不需要死记硬背,完全能通过理解整个 JVM 的执行过程来梳理出思路的。
答案
1 2 3 4 5 6 7 8 9 10 11 |
|
参考:
- 《Java 构造方法中的执行顺序》
- 《Java 类的装载、链接和初始化》
原文地址:http://biaobiaoqi.me/blog/2013/09/22/java-initialization/
版权声明:自由转载-非商用-非衍生-保持署名| Creative Commons BY-NC-ND 3.0
转载于:https://www.cnblogs.com/biaobiaoqi/p/3334049.html
Java类、实例的初始化顺序相关推荐
- Java类中的初始化顺序
根据<Thinking in Java>相关章节及自己的理解举例来说明类初始化顺序. public class InitialOrder {private static String st ...
- Java类中变量初始化顺序
下面代码显示了静态初始化代码块,非静态实例初始化代码块,构造函数 等在Java中从代码载入内存到代码执行过程的执行顺序: import static net.mindview.util.Print.* ...
- php中继承过来的类初始化顺序,java_图文详解Java中class的初始化顺序,class的装载
在讲class的初始化 - phpStudy...
图文详解Java中class的初始化顺序 class的装载 在讲class的初始化之前,我们来讲解下class的装载顺序. 以下摘自<Thinking in Java 4> 由于Java ...
- 【转载】c#类的成员初始化顺序
作者:彭白洋 创建于:2009-01-15 出处:http://www.cnblogs.com/siceblue/archive/2009/01/15/1376430.html 收录于:2013-0 ...
- 构造方法、类的初始化块以及类字段的初始化顺序
构造方法 首先,以下代码为何无法通过编译?哪儿出错了? public class Test {public static void main(String[] args) {Foo obj1 = ne ...
- c++构造函数以及类中变量初始化顺序
c++构造函数以及类中变量初始化顺序 Submitted by ant on Fri, 03/29/2013 - 20:05 构造函数 c++ 的类提供了一种抽象机制,使用起来要比 c 方便很多.为了 ...
- C++结构体实例和类实例的初始化
结构体实例(包括共用体)和类实例的初始化方法完全相同,二者都可以应用于继承层次中.不同点是结构体(包括共用体)默认成员为public,而类默认成员是private型的. 一.若类和结构体所有数据成员均 ...
- C++结构体实例和类实例的初始化 .
结构体实例(包括共用体)和类实例的初始化方法完全相同,二者都可以应用于继承层次中.不同点是结构体(包括共用体)默认成员为public,而类默认成员是private型的. 一.若类和结构体所有数据成员均 ...
- java中具有继承关系的类及其对象初始化顺序
先说结论 对于具有继承关系的类,它们的类和对象构造顺序为:父类的类构造器() -> 子类的类构造器() -> 父类成员变量的赋值和实例代码块 -> 父类的构造函数 -> 子类成 ...
最新文章
- python中的doc_基于Python获取docx/doc文件内容代码解析
- 马斯克:人脑“带宽”有限,需要用人工智能加持提高连接速度
- sqlserver date类型和字符串比较_VB编程基本数据类型完整剖析
- T-SQL :SQL Server 定义数据完整性 5大约束
- 全缓冲、行缓冲和无缓冲
- mfc tabcontrol 修改白色背景_初级会计报名准备工作如何使用美图秀秀PC版修改照片尺寸、格式、大小...
- ROS在类中发布和接受消息(自定义消息)
- java 异常处理向处机制笔记
- 邮件 查看html源码,微软 Win10解决邮件显示HTML源代码的问题
- 转移到ios下载安卓_转移到ios下载-转移到ios app下载v2.10.0 安卓最新版-2265安卓网...
- 进销存excel_Excel仓库进销存管理系统,全函数库存,查询汇总自动生成超简单...
- 第一行代码(Android)第二版PDF和源码
- 机器学习——训练模型
- 实验报告 三 密码破解技术
- min-max之间取随机数公式
- cf卡格式化后还能数据恢复么?相机cf卡误删怎么恢复
- 程序猿成长之路之密码学篇-DES介绍
- 做外贸十大不能接的订单!
- WGS84经纬度坐标6度分带高斯投影正算
- uni 讯飞文字转语音 详解
热门文章
- java8泛型包括_JAVA8 获取泛型类型问题
- mysql求和语句大全_sql查询语句大全
- rtsp 报文转发_rtsp_proxy_server
- 大android 平板,15.6英寸安卓大平板? 阿芙罗S1评测
- linux下批量新增数据,linux下批量插入数据到mysql
- mysql 组内排名_【原】MySQL分组排序(包含组内排名、求中位数)
- php多图片上传程序2.4.3,php多文件上传 多图片上传程序代码
- linux snmp 限制ip_Windows/Linux服务器监控软件推荐
- # 字节数组转uint32_字节跳动客户端校招面经(21届秋招内推)
- java script eval_「eval」js中的eval方法详解(一)–eval方法的初级应用 - seo实验室...