今晚是阿里巴巴 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
class T  implements Cloneable{  public static int k = 0;
  public static T t1 = new T("t1");
  public static T t2 = new T("t2");
  public static int i = print("i");
  public static int n = 99;

  public int j = print("j");
  {      print("构造快");
  }

  static {      print("静态块");
  }

  public T(String str) {      System.out.println((++k) + ":" + str + "    i=" + i + "  n=" + n);
      ++n; ++ i;
  }

  public static int print(String str){      System.out.println((++k) +":" + str + "   i=" + i + "   n=" + n);
      ++n;
      return ++ i;
  }

  public static void main(String[] args){      T t = new T("init");
  }
}

分析

代码主要考察的是类、变量初始化的顺序。

一般的,我们很清楚类需要在被实例化之前初始化,而对象的初始化则是运行构造方法中的代码。

本题的代码显然没有这么简单了。本题中涉及到了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
1:j   i=0   n=0
2:构造快   i=1   n=1
3:t1    i=2  n=2
4:j   i=3   n=3
5:构造快   i=4   n=4
6:t2    i=5  n=5
7:i   i=6   n=6
8:静态块   i=7   n=99
9:j   i=8   n=100
10:构造快   i=9   n=101
11:init    i=10  n=102

参考:

  • 《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类、实例的初始化顺序相关推荐

  1. Java类中的初始化顺序

    根据<Thinking in Java>相关章节及自己的理解举例来说明类初始化顺序. public class InitialOrder {private static String st ...

  2. Java类中变量初始化顺序

    下面代码显示了静态初始化代码块,非静态实例初始化代码块,构造函数 等在Java中从代码载入内存到代码执行过程的执行顺序: import static net.mindview.util.Print.* ...

  3. php中继承过来的类初始化顺序,java_图文详解Java中class的初始化顺序,class的装载 在讲class的初始化 - phpStudy...

    图文详解Java中class的初始化顺序 class的装载 在讲class的初始化之前,我们来讲解下class的装载顺序. 以下摘自<Thinking in Java 4> 由于Java ...

  4. 【转载】c#类的成员初始化顺序

    作者:彭白洋 创建于:2009-01-15 出处:http://www.cnblogs.com/siceblue/archive/2009/01/15/1376430.html  收录于:2013-0 ...

  5. 构造方法、类的初始化块以及类字段的初始化顺序

    构造方法 首先,以下代码为何无法通过编译?哪儿出错了? public class Test {public static void main(String[] args) {Foo obj1 = ne ...

  6. c++构造函数以及类中变量初始化顺序

    c++构造函数以及类中变量初始化顺序 Submitted by ant on Fri, 03/29/2013 - 20:05 构造函数 c++ 的类提供了一种抽象机制,使用起来要比 c 方便很多.为了 ...

  7. C++结构体实例和类实例的初始化

    结构体实例(包括共用体)和类实例的初始化方法完全相同,二者都可以应用于继承层次中.不同点是结构体(包括共用体)默认成员为public,而类默认成员是private型的. 一.若类和结构体所有数据成员均 ...

  8. C++结构体实例和类实例的初始化 .

    结构体实例(包括共用体)和类实例的初始化方法完全相同,二者都可以应用于继承层次中.不同点是结构体(包括共用体)默认成员为public,而类默认成员是private型的. 一.若类和结构体所有数据成员均 ...

  9. java中具有继承关系的类及其对象初始化顺序

    先说结论 对于具有继承关系的类,它们的类和对象构造顺序为:父类的类构造器() -> 子类的类构造器() -> 父类成员变量的赋值和实例代码块 -> 父类的构造函数 -> 子类成 ...

最新文章

  1. python中的doc_基于Python获取docx/doc文件内容代码解析
  2. 马斯克:人脑“带宽”有限,需要用人工智能加持提高连接速度
  3. sqlserver date类型和字符串比较_VB编程基本数据类型完整剖析
  4. T-SQL :SQL Server 定义数据完整性 5大约束
  5. 全缓冲、行缓冲和无缓冲
  6. mfc tabcontrol 修改白色背景_初级会计报名准备工作如何使用美图秀秀PC版修改照片尺寸、格式、大小...
  7. ROS在类中发布和接受消息(自定义消息)
  8. java 异常处理向处机制笔记
  9. 邮件 查看html源码,微软 Win10解决邮件显示HTML源代码的问题
  10. 转移到ios下载安卓_转移到ios下载-转移到ios app下载v2.10.0 安卓最新版-2265安卓网...
  11. 进销存excel_Excel仓库进销存管理系统,全函数库存,查询汇总自动生成超简单...
  12. 第一行代码(Android)第二版PDF和源码
  13. 机器学习——训练模型
  14. 实验报告 三 密码破解技术
  15. min-max之间取随机数公式
  16. cf卡格式化后还能数据恢复么?相机cf卡误删怎么恢复
  17. 程序猿成长之路之密码学篇-DES介绍
  18. 做外贸十大不能接的订单!
  19. WGS84经纬度坐标6度分带高斯投影正算
  20. uni 讯飞文字转语音 详解

热门文章

  1. java8泛型包括_JAVA8 获取泛型类型问题
  2. mysql求和语句大全_sql查询语句大全
  3. rtsp 报文转发_rtsp_proxy_server
  4. 大android 平板,15.6英寸安卓大平板? 阿芙罗S1评测
  5. linux下批量新增数据,linux下批量插入数据到mysql
  6. mysql 组内排名_【原】MySQL分组排序(包含组内排名、求中位数)
  7. php多图片上传程序2.4.3,php多文件上传 多图片上传程序代码
  8. linux snmp 限制ip_Windows/Linux服务器监控软件推荐
  9. # 字节数组转uint32_字节跳动客户端校招面经(21届秋招内推)
  10. java script eval_「eval」js中的eval方法详解(一)–eval方法的初级应用 - seo实验室...