问题

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

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

分析

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

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

以下通过具体场景说明

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

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

Base.java

  1. public class Base {
  2. public static int pub_s = method(1);
  3. private static int pri_s = method(2);
  4. public static int pub_s2 = method(3);
  5. private static int pri_s2 = method(4);
  6. private int pri1;
  7. private int pri2 = method(5);
  8. private int pri3;
  9. private int pri4 = method(6);
  10. public Base() {
  11. pri1 = method(7);
  12. pri3 = method(8);
  13. }
  14. public static int method(int i) {
  15. System.out.println(i);
  16. return i;
  17. }
  18. public static void main(String args[]) {
  19. method(0);
  20. Base b2 = new Base();
  21. }
  22. }

输出结果为

  1. 1
  2. 2
  3. 3
  4. 4
  5. 0
  6. 5
  7. 6
  8. 7
  9. 8

可以得到以下信息

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

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

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

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

Sub.java

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

运行Sub.java, 输出结果为

  1. 1
  2. 2
  3. 3
  4. 4
  5. 11
  6. 12
  7. 13
  8. 14
  9. 10
  10. 5
  11. 6
  12. 7
  13. 8
  14. 15
  15. 16
  16. 17
  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】516. Longest Palindromic Subsequence 最长回文子序列

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题思路 代码 刷题心得 日期 题目地址:https://le ...

  2. 【LeetCode】113. Path Sum II 路径总和 II 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.me/ 文章目录 题目描述 题目大意 解题方法 BFS DFS 日期 题目地址:https:// ...

  3. anaconda安装PIL

    PIL仅支持到python2.7: Pillow支持Python 3.x: conda install pillow 参考文献: 使用anaconda安装python3版本的PIL_不行不至-CSDN ...

  4. 教你Python字符串的基本操作:拆分和连接

    摘要:由于字符串数据几乎无处不在,因此掌握有关字符串的交易工具非常重要.幸运的是,Python 使字符串操作变得非常简单,尤其是与其他语言甚至旧版本的 Python 相比时. 本文分享自华为云社区&l ...

  5. JVM 内存布局

    JVM 内存布局规定了 Java 在运行过程中内存申请.分配.管理的策略,保证了 JVM 的高效稳定运行. 线程是否共享 Heap (堆区) 堆是 OOM 故障最主要的发生区域.它是内存区域中最大的一 ...

  6. 深入理解Java虚拟机一:运行时数据区域

    根据<Java虚拟机规范(第2版)>的规定,Java虚拟机管理的内存包括下图几个运行时数据区域: 1.程序计数器        程序计数器(Program Counter Register ...

  7. vue打包之后动态修改请求接口方法

    1.可以根据自身情况封装获取配置文件接口信息 1.1我在static中新建一个config.json配置文件 { "DEV_URL":"/apis",//开发模 ...

  8. find 命令常用解释

    背景色是:orange #### find命令 find * path: 所有搜索的目录以及其所有子目录.默认为当前目录 * expression: 所有搜索的文件的特征 * cmd: 对搜索结果惊醒 ...

  9. xpath如何使用正则、xpath定位svg标签、xpath常用集合

    自己用到的xpath都收集下咯!!! 持续更新本页面 xpath查找svg图标 xpath('//*[local-name() = "svg" and @class="_ ...

  10. 在 GitHub 复活 80 年代的游戏代码,它们出自第一本售出百万册的计算机书籍

    今儿我在 GitHub 看到了一个很眼熟的名字和头像,但是第一时间没想起来他是谁.算了先看看是个什么神仙开源项目,竟然能登上今天的 GitHub 趋势榜首. 该项目是把<BASIC Comput ...