由阿里巴巴一道笔试题看Java静态代码块、静态函数、动态代码块、构造函数等的执行顺序
一、阿里巴巴笔试题:
public class Test {
public static int k = 0;
public static Test t1 = new Test("t1");
public static Test t2 = new Test("t2");
public static int i = print("i");
public static int n = 99;
private int a = 0;
public int j = print("j");
{
print("构造块");
}
static {
print("静态块");
}
public Test(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
public static int print(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
public static void main(String args[]) {
Test t = new Test("init");
}
}
输出:
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
二、我们暂且先不看这道题,先回忆一下代码块、构造函数执行顺序的基本知识:
总体规则:静态代码块 -> 动态代码块 ->构造函数
静态代码块只在第一次new的时候执行一次,之后不再执行;动态代码块在每次new的时候都执行一次。
在不涉及继承的情况下:
1.静态代码块和静态成员变量在加载代码时执行,只执行一次,按照它们出现的顺序先后执行;
2.动态代码块在每次实例化对象时执行,在构造函数之前执行,多个动态代码块按照它们出现的顺序先后执行;
在涉及继承的情况下:
1.执行父类的静态代码块和静态成员变量定义,执行子类的静态代码块和静态成员变量定义;
2.执行父类的动态代码块,执行父类的构造函数;
3.执行子类的动态代码块,执行子类的构造函数;
4.如果父类构造函数中用到的函数被子类重写,那么在构造子类对象时调用子类重写的方法;
代码:
public class staticTest {
public static void main(String[] args) {
A a1 = new B();
}
}
class A{
public A(){
System.out.println("A constructor.");
func();
}
static{
System.out.println("class A static block.");
}
private int ai = getAi();
{
System.out.println("class A dynamic block.");
}
private static int asi = getAsi();
private int getAi(){
System.out.println("class A dynamic int.");
return 1;
}
private static int getAsi(){
System.out.println("class A static int.");
return 0;
}
public void func(){
System.out.println("A.func()");
}
}
class B extends A{
public B(){
System.out.println("B constructor.");
func();
}
static{
System.out.println("class B static block.");
}
private int bi = getBi();
{
System.out.println("class B dynamic block.");
}
private static int bsi = getBsi();
private int getBi(){
System.out.println("class B dynamic int.");
return 1;
}
private static int getBsi(){
System.out.println("class B static int.");
return 0;
}
public void func(){
System.out.println("B.func()");
}
}
输出:
class A static block.
class A static int.
class B static block.
class B static int.
class A dynamic int.
class A dynamic block.
A constructor.
B.func()
class B dynamic int.
class B dynamic block.
B constructor.
B.func()
三、对阿里巴巴笔试题的分析
public static int k = 0;
public static Test t1 = new Test("t1");
函数先执行到这里,在构造t1的过程中发生了什么呢,通过对程序打断点分析,我发现,程序并没有执行其中的静态代码块,而是执行非静态代码块,为什么呢?我的理解是,“静态代码块只在程序加载的时候运行,并且是按其出现顺序加载的”,而现在我们在构造一个新对象,属于程序加载的时候的一个分支,然后还会走回来继续加载剩下的未加载的静态代码块。所以在这次创建静态对象的过程中,之后执行其中的非静态代码块。
下面我们看到的两个*****中间的就是在执行该语句的过程中产生的分支:
**********
所以接下来执行的是:
private int a = 0;
public int j = print("j");
执行第二句的时候会调用
public static int print(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
然后执行动态代码块:
{
print("构造块");
}
然后调用构造函数:
public Test(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
这个顺序就是“动态代码块->构造函数"。
*************
然后跳出该分支,继续加载静态代码块:
public static Test t2 = new Test("t2");
执行此句会重复上面两个********之间的分支,这里不再赘述。
然后是:
public static int i = print("i");
public static int n = 99;
static {
print("静态块");
}
最后执行main函数里面的部分,依次调用动态代码块和构造函数,不再赘述。
由阿里巴巴一道笔试题看Java静态代码块、静态函数、动态代码块、构造函数等的执行顺序的更多相关文章
- 从阿里巴巴笔试题看Java加载顺序
一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...
- 由阿里巴巴笔试题看java加载顺序
一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...
- 一道笔试题来理顺Java中的值传递和引用传递
题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...
- Java中有关构造函数的一道笔试题解析
Java中有关构造函数的一道笔试题解析 1.详细题目例如以下 下列说法正确的有() A. class中的constructor不可省略 B. constructor必须与class同名,但方法不能与c ...
- 【笔试题】Java笔试题知识点
Java高概率笔试题知识点 Java语法基础部分 [解析]java命令程序执行字节码文件是,不能跟文件的后缀名! 1.包的名字都应该是由小写单词组成,它们全都是小写字母,即便中间的单词亦是如此 2.类 ...
- 一道笔试题和UML思想 ~
一句软件工程界的名言,让我想起了一个和一道笔试题有关的故事.希望更多的人了解 UML 背后的思想比他的语法更重要,是笔者写作本文的一点小愿望. 一.从一句软件工程名言说起 对很多事情的处理上,东西方都 ...
- Java静态变量的初始化(static块的本质)
Java静态变量的初始化(static块的本质) 标签: javaclassstring编译器jdk工作 2010-02-06 07:23 33336人阅读 评论(16) 收藏 举报 分类: Jav ...
- Java静态变量、静态块、构造块、构造函数、main函数、普通代码块的执行顺序
测试代码 public class SingleTest { public static String v = "StaticValue"; static { System.out ...
- 一道面试题与Java位操作 和 BitSet 库的使用
前一段时间在网上看到这样一道面试题: 有个老的手机短信程序,由于当时的手机CPU,内存都很烂.所以这个短信程序只能记住256条短信,多了就删了. 每个短信有个唯一的ID,在0到255之间.当然用户可能 ...
随机推荐
- overflow第一次觉得你有点可恶
今天用css做下拉菜单,因为不需要做手机自适应,再手机里看起来工整一点就行,可是列表中最后一个li的宽度撑开了父div,导致看起来很糟糕,所以给父元素加overflow:hidden:但是下拉列表也被 ...
- 给id赋值
var div = document.getElementByTagName('div') div.id="mydiv";div.setAttribute("id&quo ...
- 我的css reset
@charset "utf-8"; /*reset*/ body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,f ...
- Jquery 全选、反选
jQuery 1.9以后用 prop(); 不用attr 等 $(function() { $('#inputCheck').click(function() { $("input[name ...
- C语言知识总结
明白一些变量 熟悉一些语句 组合一些函数 C语言——>库 帮你写好放在库中 魔数 凭空变出来的数字,不知道 数字表示的含义,影响代码的可读性. C语音的参数传递 非常特殊,传递的是一个替身. ...
- pycharm console 控制台乱码的解决
- SequoiaDB 架构指南
1 简介 SequoiaDB(巨杉数据库)是一款分布式非关系型文档数据库,可以被用来存取海量非关系型的数据,其底层主要基于分布式,高可用,高性能与动态数据类型设计,与当前主流分布式计算框架 Hadoo ...
- A Knight's Journey
poj2488:http://poj.org/problem?id=2488 题意:给你一张地图,然后有一个骑士,骑士可以从地图的任意一个方格开始,作为起点,问你该骑士能否走遍整张题图.题解:首先想到 ...
- ParentWindow属性及其一系列函数的作用——适合于那些不需要父控件管理内存释放的子控件
TWinControl = class(TControl) property ParentWindow: HWnd read FParentWindow write SetParentWindow; ...
- 如何给div加一个边框border样式
如何给div加一个边框样式? 对div盒子加一个边框样式很简单只需要使用border板块样式即可. 一.虚线与实线边框 边框虚线样式:dashed 边框实现样式:solid border:1px da ...