前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面试题丨Java的类/实例初始化过程

面试题丨Java的类/实例初始化过程

原创
作者头像
本人秃顶程序员
修改于 2019-05-14 02:08:23
修改于 2019-05-14 02:08:23
99400
代码可运行
举报
文章被收录于专栏:Java架构筑基Java架构筑基
运行总次数:0
代码可运行

昨天看到群里面有人分享了一道题目,我答错了,于是趁机了解了下Java的类/对象初始化过程:

程序A主要考察的是类实例初始化。简单验证了下,类实例初始化过程如下:

  • 父类实例初始化
  • 构造块/变量初始化(按照文本顺序执行)
  • 构造函数

程序B考察的则是类初始化。类初始化的过程如下:

  • 父类初始化
  • static变量初始化/static块(按照文本顺序执行)

但是我们必须做到面向接口编程,而不是面向实现编程(Program to an ‘interface’, not an ‘implementation’)。

于是就得看看Java Language Specification了。其中类初始化过程如下:

  1. 每个类都有一个初始化锁LC,进程获取LC(如果没有获取到,就一直等待)
  2. 如果C正在被其他线程初始化,释放LC并等待C初始化完成
  3. 如果C正在被本线程初始化,即递归初始化,释放LC
  4. 如果C已经被初始化了,释放LC
  5. 如果C处于erroneous状态,释放LC并抛出异常NoClassDefFoundError
  6. 否则,将C标记为正在被本线程初始化,释放LC;然后,初始化那些final且为基础类型的类成员变量
  7. 初始化C的父类SC和各个接口SI_n(按照implements子句中的顺序来) ;如果SC或SIn初始化过程中抛出异常,则获取LC,将C标记为erroneous,并通知所有线程,然后释放LC,然后再抛出同样的异常。
  8. 从classloader处获取assertion是否被打开
  9. 接下来,按照文本顺序执行类变量初始化和静态代码块,或接口的字段初始化,把它们当作是一个个单独的代码块
  10. 如果执行正常,获取LC,标记C为已初始化,并通知所有线程,然后释放LC
  11. 否则,如果抛出了异常E。若E不是Error,则以E为参数创建新的异常ExceptionInInitializerError作为E。如果因为OutOfMemoryError导致无法创建ExceptionInInitializerError,则将OutOfMemoryError作为E。
  12. 获取LC,将C标记为erroneous,通知所有等待的线程,释放LC,并抛出异常E。

可以看到JLS确实规定了父类先初始化(7)、static块和类变量赋值按照文本顺序来(9)。

欢迎加入Java技术交流Qqun:963944895

然后看看类实例的初始化

  1. 开始调用构造函数(给参数赋值)
  2. 如果这个构造函数在开始就调用了其他构造函数,那么调用新的构造函数,并按照本规则处理。如果执行过程中抛出异常,则整个过程也抛出同样的异常。如果正常,继续。
  3. 如果构造函数没有在开始就调用其他构造函数。如果本类不是Object,那么构造函数会隐式或者显式的调用父类的构造方法。父类构造方法也依本规则处理。如果执行过程中抛出异常,则整个过程也抛出同样的异常。如果正常,继续。
  4. 执行实例初始化和实例变量初始化。顺序按照文本顺序来处理——从左到右、从上到下。如果执行过程中抛出异常,则整个过程也抛出同样的异常。如果正常,继续。
  5. 执行剩下的构造函数。如果执行过程中抛出异常,则整个过程也抛出同样的异常。

JLS特意提到,如果子类覆盖了父类的方法,则在构造函数中,调用的方法也是子类的

接下来一个一个看代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 程序A
// 父类
class Parent {
    int i = 1;
    Parent() {
        System.out.println(i);
        int x = getValue();
        System.out.println(x);
    }
    {i = 2;}
    protected int getValue() {return i;}
}
// 子类
class Son extends Parent {
    int j = 1;
    Son() {j = 2;}
    protected int getValue() {return j;}
}
class Test {
    public static void main(String[] args) {
        Son son = new Son();
        System.out.println(son.getValue());
    }
}
  1. 21行,开始调用Son的构造函数
  2. 16行,Son的构造函数开始之前,初始化Parent
  3. 4行,开始执行i的变量初始化
  4. 10行,开始执行构造代码块
  5. 6-8行,开始执行Parent的构造函数。注意,调用的getValue方法是子类的,而此时Son.j还没有被构造函数、变量赋值语句初始化,此时Son.j是0。(输出2,0)
  6. 回到16行,继续执行Son的构造函数
  7. 22行,打印此时Son.j的值。(输出2)

所以,程序A的输出是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2
0
2

接下来看程序B:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 程序B
public class MagimaTest {
    public static void main(String[] args) {
        magimaFunction();
    }
    static MagimaTest st = new MagimaTest();
    static {
        System.out.println("1");
    }
    {
        System.out.println("2");
    }
    MagimaTest() {
        System.out.println("3");
        System.out.println("a=" + a + ",b=" + b);
    }
    public static void magimaFunction() {
        System.out.println("4");
    }
    int a = 110;
    static int b = 112;
}
  1. 3行,在执行main之前,需要初始化MagimaTest类。
  2. 6行,初始化st成员变量,开始初始化st实例。
  3. 13开始调用构造函数,但是开始前,需要处理成员变量初始化
  4. 10行,执行构造代码块(输出2)
  5. 20行,初始化a变量
  6. 14行,继续执行构造函数。此时a为110,b尚未初始化,所以是0(输出3,a=110,b=0)
  7. 7行,st成员变量初始化结束,执行下一个static代码块(输出1)
  8. 21行,继续初始化下一个static成员变量b
  9. 4行,调用magimaFunction(输出4)
  10. 欢迎加入Java技术交流Qqun:963944895

所以输出是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2
3
a=110,b=0
1
4

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Postman被低估的功能 — 自动化接口测试
该篇文章针对已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求的操作。
架构师修炼
2021/11/02
3.6K0
自动化测试
自动化测试的本质是先写一段代码,然后去测试另一段代码,所以实现自动化测试用例本身属于开发工作,需要投入大量的时间和精力,并且已经开发完成的用例还必须随着被测对象的改变而不断更新,你还需要为此付出维护测试用例的成本。
zx钟
2019/07/19
1.2K0
Postman被低估的功能,接口自动化测试效率杠杆的!
Hi,大家好。在此之前,介绍了利用Postman进行数据模拟:如何用Postman mock服务?
可可的测试小栈
2021/11/17
9450
Postman被低估的功能,接口自动化测试效率杠杆的!
全网最全的Postman接口自动化测试!(菜鸟级攻略)
该篇文章针对已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求的操作。
测试小兵
2023/03/03
1.3K0
全网最全的Postman接口自动化测试!(菜鸟级攻略)
一文搞定Postman接口自动化测试
本文适合已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求等基本操作。
lyb-geek
2020/02/11
1.5K0
一文搞定Postman接口自动化测试
使用postman进行API自动化测试
而且在使用时需要登录账号,我这边是直接登录的Google账号-。-貌似有其它方式,但是我并没有去尝试。
贾顺名
2019/12/09
7110
使用postman进行API自动化测试
使用postman进行API自动化测试
使用postman进行API自动化测试 最近在进行一个老项目的升级,第一步是先将node版本从4.x升级到8.x,担心升级会出现问题,所以需要将服务的接口进行验证; 如果手动输入各种URL,人肉check,一个两个还行,整个服务。。大几十个接口,未免太浪费时间了-.-; 因为是一个纯接口服务的项目,所以打算针对对应的API进行一波自动化测试; 所以就开始寻找对应的工具,突然发现,平时使用的PostMan貌似也是支持写测试用例的-.-,所以就照着文档怼了一波; 一下午的时间,很是激
贾顺名
2018/04/12
1.5K0
使用postman进行API自动化测试
Postman 最被低估的功能!
该篇文章针对已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求的操作。
码农架构
2021/11/10
5200
Postman 最被低估的功能!
使用postman 自动化测试接口
软件测试是软件开发的重要组成部分,是贯穿整个软件生命周期,对软件产品进行验证和确认的活动过程,其目的是尽早发现软件产品中存在的各种问题,如与用户需求、预先定义不一致等问题。
狂奔滴小马
2021/11/15
1K0
使用postman 自动化测试接口
软件测试|Postman做 接口自动化测试
本文适合已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求等基本操作。
霍格沃兹测试开发Muller老师
2023/01/09
6500
Postman中的断言
主要分享测试的学习资源,帮助快速了解测试行业,帮助想转行、进阶、小白成长为高级测试工程师。
伤心的辣条
2022/12/14
9630
Postman中的断言
阿常:自动化测试杂谈
自动化测试的本质是先写一段代码,然后去测试另一段代码,所以实现自动化测试用例本身属于开发工作,需要投入大量的时间和精力,并且已经开发完成的用例还必须随着被测对象的改变而不断更新,你还需要为此付出维护测试用例的成本。
程序媛淼淼
2022/09/01
2030
Postman----API接口测试神器
API是用于构建应用程序软件的一组子程序定义,协议和工具。一般来说,这是一套明确定义的各种软件组件之间的通信方法。 API测试——测试API集合,检查它们的功能、性能、安全性,以及是否返回正确的响应。
洛米唯熊
2019/07/25
4.1K0
Postman----API接口测试神器
【自动化测试】是否有必要做自动化测试?
在一些测试交流群经常会看到有小伙伴在问,"怎么做自动化测试?学习自动化测试有什么资料吗?自动化测试是不是很牛逼?" ,甚至有些言论是"不会自动化的测试人员,真的要被淘汰了吗?"
用户9913368
2022/08/13
5500
接口测试|Postman设置断言
作为一款接口测试工 具,postman需要对发送请求后返回的结果是否正确做验证,在postman中通过 tests页签做请求的验证,也称为断言。
霍格沃兹测试开发Muller老师
2023/01/31
1.1K0
Postmant压力测试
下面是在网上随便抓了一个请求地址来做演示,把请求地址填入地址栏,此请求为GET请求。点击Send发送请求,请求结果将会在下方显示出来。每次的请求历史数据,会被记录下来,但是经常使用的请求,还是保存一下,这么每次用的时候,选择就行了,及其方便。
cywhat
2022/11/22
2K0
Postmant压力测试
postman安装使用教程_postman怎么使用
第一部分:基础篇postman1.安装postman进入postman官网,如果是mac系统可以直接点击mac app安装
全栈程序员站长
2022/09/30
2.7K0
postman安装使用教程_postman怎么使用
【实践】2.如何使用Postman做多接口测试
本文讲解使用postman做接口测试和批量接口测试的方法。Postman的入门参考《【知识】1.Postman接口测试神器从安装到精通》
辉哥
2021/04/16
2.5K0
【实践】2.如何使用Postman做多接口测试
接口测试之Postman使用全指南(原来使用 Postman测试API接口如此简单)
做接口测试的好处: 1、节约时间,缩短项目成本 2、提高工作效率 3、提高系统的健壮性
全栈程序员站长
2022/09/04
3.8K0
接口测试之Postman使用全指南(原来使用 Postman测试API接口如此简单)
自动化测试和软件测试是一样的吗?
1)手工测试发现的缺陷多:因为人是有智慧的,可以自觉判断更多的问题和现象,找出更多的缺陷。
wencheng
2022/08/25
6470
相关推荐
Postman被低估的功能 — 自动化接口测试
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档