问题

这也是Java面试中出镜率很高的基础概念问题

  • 描述一下多级继承中字段初始化顺序
  • 描述一下多级继承中类变量初始化顺序
  • 写出运行以下代码时的控制台输出
public class Base {
public static int v1 = method(1);
private static int v2 = method(2); private int v3;
private int v4 = method(3); public Base() {
v3 = method(4);
}
public static int method(int i) {
System.out.println(i);
return i;
}
public static void main(String args[]) {
method(5);
Base b2 = new Base();
}
}

分析

正确回答这些问题, 需要对以下的概念有了解:

  1. static关键字, 静态变量和静态方法
  2. 静态变量和普通成员变量初始化的区别
  3. 类初始化中父类和子类变量的初始化顺序

以下通过具体场景说明

场景一: 单个类的初始化顺序

先看单个类的初始化顺序, 静态和普通变量都根据public和private区分, 交替声明.

Base.java

public class Base {
public static int pub_s = method(1);
private static int pri_s = method(2);
public static int pub_s2 = method(3);
private static int pri_s2 = method(4); private int pri1;
private int pri2 = method(5);
private int pri3;
private int pri4 = method(6); public Base() {
pri1 = method(7);
pri3 = method(8);
}
public static int method(int i) {
System.out.println(i);
return i;
}
public static void main(String args[]) {
method(0);
Base b2 = new Base();
}
}

输出结果为

1
2
3
4
0
5
6
7
8

可以得到以下信息

  1. 静态成员变量初始化最早

    • 与实例初始化无关, 在载入类时完成初始化
    • 初始化顺序与代码顺序一致, 与public还是private无关
  2. 静态成员变量初始化在执行main()函数之前完成, 因为在执行main()函数前, 静态成员初始化就伴随类的载入完成了
  3. 普通成员变量初始化在执行构造函数之前

场景二: 带继承关系的类初始化顺序

保持Base.java不变, 增加Sub.java作为子类

Sub.java

public class Sub extends Base {
public static int sub_pub_s = method(11);
private static int sub_pri_s = method(12);
public static int sub_pub_s2 = method(13);
private static int sub_pri_s2 = method(14); private int sub_pri1;
private int sub_pri2 = method(15);
private int sub_pri3;
private int sub_pri4 = method(16); public Sub() {
sub_pri1 = method(17);
sub_pri3 = method(18);
}
public static void main(String args[]) {
method(10);
Sub b2 = new Sub();
}
}

运行Sub.java, 输出结果为

1
2
3
4
11
12
13
14
10
5
6
7
8
15
16
17
18

可以得到以下信息

  1. 在任何情况下, 静态成员变量都会最先初始化
  2. 在存在继承关系的类中, 父类的静态成员变量先初始化, 然后是子类的静态成员变量
  3. 所有静态成员变量初始化之后, 才开始main函数的执行
  4. 在类实例初始化过程中, 先初始化父类, 再初始化子类, 每一层都是先成员变量, 然后执行构造函数, 所以顺序就是: 父类成员变量, 父类构造函数, 子类成员变量, 最后是子类构造函数

总结

类的构造顺序为

  1. 父类静态成员变量, 其顺序与代码顺序一致, 与public还是private无关
  2. 子类静态成员变量, 其顺序与代码顺序一致, 与public还是private无关
  3. 如果执行类的静态函数(包括main函数), 这个时间点就会开始执行函数
  4. 如果创建了类的实例, 注意这个前提, 下面就会开始普通成员变量的初始化
  5. 父类的普通成员变量
  6. 父类的构造函数
  7. 子类的普通成员变量
  8. 子类的构造函数

Java语法专题2: 类变量的初始化顺序的更多相关文章

  1. Java语法专题1: 类的构造顺序

    合集目录 Java语法专题1: 类的构造顺序 问题 下面的第二个问题来源于Oracle的笔试题, 非常经典的一个问题, 我从07年开始用了十几年. 看似简单, 做对的比例不到2/10. 描述一下多级继 ...

  2. Java类继承关系中的初始化顺序

    Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类Ini ...

  3. Java杂谈3——类加载机制与初始化顺序

    Java语言的哲学:一切都是对象.对于Java虚拟机而言,一个普通的Java类同样是一个对象,那如果是对象,必然有它的初始化过程.一个类在JVM中被实例化成一个对象,需要经历三个过程:加载.链接和初始 ...

  4. IT兄弟连 Java语法教程 数组 数组的初始化

    Java语言中数组必须先初始化,然后才可以使用.所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值. 这时有人会问,能不能只分配内存空间,不赋初始值呢?答案是肯定不行的,一旦为数组 ...

  5. Java中类的数据成员的初始化顺序

    对于单一类: 属性初始化 ---> 按顺序执行静态初始化块(只能操作静态属性) ---> 按顺序执行初始化块 ---> 构造方法 对于存在继承关系的类: 父类属性初始化 ---> ...

  6. java类的加载以及初始化顺序

    类的加载和初始化的了解对于我们对编程的理解有很大帮助,最近在看类的记载方面的问题.从网上查阅了若干文章,现总结如下: 我们通过一段代码来了解类加载和初始化的顺序: package com.classl ...

  7. Java中含有静态成员的的初始化顺序

    class Bowl{ Bowl(int marker){ System.out.println("Bowl(" + marker + ")" ); } voi ...

  8. java对象中继承和变量初始化顺序浅析

    先上例子代码 public class F { int age = 5; public F() { print(); } public void print() { System.out.printl ...

  9. 【深入理解JVM】:Java类继承关系中的初始化顺序

    尝试着仔细阅读thinking in java 看到一篇很好的文章http://blog.csdn.net/u011080472/article/details/51330114

随机推荐

  1. 【LeetCode】31. Next Permutation 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 逆序数字交换再翻转 库函数 日期 题目地址:http ...

  2. CONTRASTIVE REPRESENTATION DISTILLATION

    目录 概 主要内容 超参数的选择 代码 Tian Y., Krishnan D., Isola P. CONTRASTIVE REPRESENTATION DISTILLATION. arXiv pr ...

  3. Adversarial Examples Improve Image Recognition

    Xie C, Tan M, Gong B, et al. Adversarial Examples Improve Image Recognition.[J]. arXiv: Computer Vis ...

  4. CH7511|LT7211|PS8625替代方案 CS5211 设计EDP转LVDS优势方案原理图+PCB板设计

    CH7511|LT7211|PS8625这三款都是专门用于设计EDP转LVDS转接板或者屏转换方案板,CH7511.LT7211.PS8625目前这几款都是出于缺货状态,台湾瑞奇达Capstone 新 ...

  5. HTML5 +Java基础 大一结业认证考试试题 - 云南农业职业技术学院 - 互联网技术学院 - 美和易思校企合作专业

     第1题 [单选题][0.33分][概念理解] 关于java中的逻辑运算符,下列说法正确的是 逻辑运算符||.&&.!都是用于连接两个关系表达式</p> 当&&am ...

  6. Java面向对象笔记 • 【第9章 JDBC编程】

    全部章节   >>>> 本章目录 9.1 JDBC基础 9.1.1 JDBC简介 9.1.2 JDBC常用API简介 JDBC 常用API功能说明 9.1.3 JDBC编程步骤 ...

  7. C# double类型精度丢失问题

    我们先看一段代码,可以在控制台程序中执行看看结果 { double d = 500; double d1 = 233.84; double d2 = d - d1; //d2=266.15999999 ...

  8. oceanbase数据库比赛总结

    前言 ob数据库大赛由蚂蚁金服的oceanbase团队组织,今年是第一届,宣传很广,比赛十月份开始,但早在上半年就看见大量的宣传了,比赛也是相当的卷.我们进了复赛之后感觉要卷进决赛需要付出的时间精力都 ...

  9. 集合不安全之 ArrayList及其三种解决方案【CopyOnWriteArrayList 、synchronizedList、Vector 】

    @ 目录 一.前言 二.为什么线程不安全 三.解决方案一CopyOnWriteArrayList (推荐,读多写少场景) 四.Collections.synchronizedList(加锁) 五.Ve ...

  10. 初识python: xlsxwriter 将数据写入Excel

    使用 xlsxwriter 模块将数据写入excel . #!/user/bin env python # author:Simple-Sir # time:2020/9/24 12:51 # 使用 ...