Java语法专题2: 类变量的初始化顺序
- 合集目录
- Java语法专题2: 类变量的初始化顺序
问题
这也是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();
}
}
分析
正确回答这些问题, 需要对以下的概念有了解:
static
关键字, 静态变量和静态方法- 静态变量和普通成员变量初始化的区别
- 类初始化中父类和子类变量的初始化顺序
以下通过具体场景说明
场景一: 单个类的初始化顺序
先看单个类的初始化顺序, 静态和普通变量都根据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
可以得到以下信息
- 静态成员变量初始化最早
- 与实例初始化无关, 在载入类时完成初始化
- 初始化顺序与代码顺序一致, 与public还是private无关
- 静态成员变量初始化在执行main()函数之前完成, 因为在执行main()函数前, 静态成员初始化就伴随类的载入完成了
- 普通成员变量初始化在执行构造函数之前
场景二: 带继承关系的类初始化顺序
保持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
可以得到以下信息
- 在任何情况下, 静态成员变量都会最先初始化
- 在存在继承关系的类中, 父类的静态成员变量先初始化, 然后是子类的静态成员变量
- 所有静态成员变量初始化之后, 才开始main函数的执行
- 在类实例初始化过程中, 先初始化父类, 再初始化子类, 每一层都是先成员变量, 然后执行构造函数, 所以顺序就是: 父类成员变量, 父类构造函数, 子类成员变量, 最后是子类构造函数
总结
类的构造顺序为
- 父类静态成员变量, 其顺序与代码顺序一致, 与public还是private无关
- 子类静态成员变量, 其顺序与代码顺序一致, 与public还是private无关
- 如果执行类的静态函数(包括main函数), 这个时间点就会开始执行函数
- 如果创建了类的实例, 注意这个前提, 下面就会开始普通成员变量的初始化
- 父类的普通成员变量
- 父类的构造函数
- 子类的普通成员变量
- 子类的构造函数
Java语法专题2: 类变量的初始化顺序的更多相关文章
- Java语法专题1: 类的构造顺序
合集目录 Java语法专题1: 类的构造顺序 问题 下面的第二个问题来源于Oracle的笔试题, 非常经典的一个问题, 我从07年开始用了十几年. 看似简单, 做对的比例不到2/10. 描述一下多级继 ...
- Java类继承关系中的初始化顺序
Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类Ini ...
- Java杂谈3——类加载机制与初始化顺序
Java语言的哲学:一切都是对象.对于Java虚拟机而言,一个普通的Java类同样是一个对象,那如果是对象,必然有它的初始化过程.一个类在JVM中被实例化成一个对象,需要经历三个过程:加载.链接和初始 ...
- IT兄弟连 Java语法教程 数组 数组的初始化
Java语言中数组必须先初始化,然后才可以使用.所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值. 这时有人会问,能不能只分配内存空间,不赋初始值呢?答案是肯定不行的,一旦为数组 ...
- Java中类的数据成员的初始化顺序
对于单一类: 属性初始化 ---> 按顺序执行静态初始化块(只能操作静态属性) ---> 按顺序执行初始化块 ---> 构造方法 对于存在继承关系的类: 父类属性初始化 ---> ...
- java类的加载以及初始化顺序
类的加载和初始化的了解对于我们对编程的理解有很大帮助,最近在看类的记载方面的问题.从网上查阅了若干文章,现总结如下: 我们通过一段代码来了解类加载和初始化的顺序: package com.classl ...
- Java中含有静态成员的的初始化顺序
class Bowl{ Bowl(int marker){ System.out.println("Bowl(" + marker + ")" ); } voi ...
- java对象中继承和变量初始化顺序浅析
先上例子代码 public class F { int age = 5; public F() { print(); } public void print() { System.out.printl ...
- 【深入理解JVM】:Java类继承关系中的初始化顺序
尝试着仔细阅读thinking in java 看到一篇很好的文章http://blog.csdn.net/u011080472/article/details/51330114
随机推荐
- 【LeetCode】820. 单词的压缩编码 Short Encoding of Words(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode-cn.com/problems/short- ...
- 1137 - Expanding Rods
1137 - Expanding Rods PDF (English) Statistics Forum Time Limit: 0.5 second(s) Memory Limit: 32 M ...
- VMware15 虚拟机分别设置连接笔记本的WLAN和以太网双网络
VMware15 虚拟机分别设置连接笔记本的WLAN和以太网双网络 虚拟机:window 10 主机: window 10 VVmware有3种网络连接模式:桥接.NAT.主机模式,默认分别对应VMN ...
- C++判断月份天数(判断闰年)
题目描述 输入年份和月份,输出这一年的这一月有多少天.需要考虑闰年. 输入格式 无 输出格式 无 输入输出样例 输入 #1 输出 #1 1926 8 31 输入 #2 输出 #2 2000 2 29 ...
- PowerDotNet平台化软件架构设计与实现系列(11):日志平台
所有后端应用几乎都会记录日志,日志系统可以统一抽象出来提供服务. 最近被Log4j2的安全漏洞刷屏了,作为开发人员的我只能咩哈哈几次表示日志处理太难了,只有折腾过的人才知道这里面的艰辛啊. 在实现Po ...
- 使用 jQuery 中的淡入淡出动画,实现图片的轮播效果,每隔 2 秒钟切换一张图片,共 6 张图片
查看本章节 查看作业目录 需求说明: 使用 jQuery 中的淡入淡出动画,实现图片的轮播效果,每隔 2 秒钟切换一张图片,共 6 张图片,切换到第 6 张后从头开始切换,在图片的下方显示 6 个小圆 ...
- Android studio 报错 Unable to resolve dependency for ‘:app@releaseUnitTest/compileClasspath‘:
出现报错: Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not find any ...
- 编写Java程序,使用PreparedState实现对英雄数据的新增、删除和更新
返回本章节 返回作业目录 需求说明: 使用PreparedState实现对英雄数据的新增.删除和更新 英雄(t_hero)表结构 列名(含义) 数据类型 约束 id (序号) int 主键,自动增长 ...
- RabbitMQ基础教程系列
Ubuntu16.04下,erlang安装和rabbitmq安装步骤 Ubuntu16.04下,rabbimq集群搭建 C# .net 环境下使用rabbitmq消息队列 .net core使用rab ...
- Swoole 协程的并发调用及使用示例
示例一: 利用通道pop会自动挂起当前协程,等待生产者推送数据的特性,实现并发调用,并在协程完成后组合结果集. $serv = new Swoole\Http\Server("127.0.0 ...