一、阿里巴巴笔试题:

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静态代码块、静态函数、动态代码块、构造函数等的执行顺序的更多相关文章

  1. 从阿里巴巴笔试题看Java加载顺序

    一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...

  2. 由阿里巴巴笔试题看java加载顺序

    一.阿里巴巴笔试题: public class T implements Cloneable { public static int k = 0; public static T t1 = new T ...

  3. 一道笔试题来理顺Java中的值传递和引用传递

      题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...

  4. Java中有关构造函数的一道笔试题解析

    Java中有关构造函数的一道笔试题解析 1.详细题目例如以下 下列说法正确的有() A. class中的constructor不可省略 B. constructor必须与class同名,但方法不能与c ...

  5. 【笔试题】Java笔试题知识点

    Java高概率笔试题知识点 Java语法基础部分 [解析]java命令程序执行字节码文件是,不能跟文件的后缀名! 1.包的名字都应该是由小写单词组成,它们全都是小写字母,即便中间的单词亦是如此 2.类 ...

  6. 一道笔试题和UML思想 ~

    一句软件工程界的名言,让我想起了一个和一道笔试题有关的故事.希望更多的人了解 UML 背后的思想比他的语法更重要,是笔者写作本文的一点小愿望. 一.从一句软件工程名言说起 对很多事情的处理上,东西方都 ...

  7. Java静态变量的初始化(static块的本质)

    Java静态变量的初始化(static块的本质) 标签: javaclassstring编译器jdk工作 2010-02-06 07:23 33336人阅读 评论(16) 收藏 举报  分类: Jav ...

  8. Java静态变量、静态块、构造块、构造函数、main函数、普通代码块的执行顺序

    测试代码 public class SingleTest { public static String v = "StaticValue"; static { System.out ...

  9. 一道面试题与Java位操作 和 BitSet 库的使用

    前一段时间在网上看到这样一道面试题: 有个老的手机短信程序,由于当时的手机CPU,内存都很烂.所以这个短信程序只能记住256条短信,多了就删了. 每个短信有个唯一的ID,在0到255之间.当然用户可能 ...

随机推荐

  1. PhotoSwipe.js 相册展示插件学习

    PhotoSwipe.js官网:http://photoswipe.com/,在这个网站上可以下载到PhotoSwipe的文件以及相关的例子. 这个组件主要是用来展示图片.相册用的,还是很实用的. 一 ...

  2. angular post发送请求和GET发送请求,服务器端接收不到信息的问题

    参数可能因为编码原因,服务器端无法接收到传递的值, 这时需要用到补丁来解决这个问题 1,下载一个http.patch.js文件,放入YII框架中的js/ng文件架内 2angularjs 创建模型部分 ...

  3. DEDECMS栏目自定义字段添加

    用到的文件: catalog_add.htm  路径:\dede\templets\ catalog_edit.htm  路径:\dede\templets\  catalog_add.php  路径 ...

  4. 提高Order by语句查询效率的两个思路

    提高Order by语句查询效率的两个思路 2011-03-01 13:07 水太深 ITPUB 字号:T | T 在MySQL数据库中,Order by语句的使用频率是比较高的.但是众所周知,在使用 ...

  5. 转:PHP的线程安全ZTS与非线程(NTS)安全版本的区别

    原文来自于:http://blog.sina.com.cn/s/blog_94c21e8f0101s2ic.html Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和 ...

  6. 【译】UI设计基础(UI Design Basics)--为iOS设计(Design for iOS)(二)

    2.1 为iOS设计(Design for iOS) iOS体现以下主题: 遵从:UI帮助用户理解界面内容并与内容交互,但绝不会与内容相互冲突. 清晰:文本在任何尺寸下都是清晰易读,图标精确易懂,装饰 ...

  7. BZOJ 1487 无归岛

    Description Neverland是个神奇的地方,它由一些岛屿环形排列组成,每个岛上都生活着之中与众不同的物种.但是这些物种都有一个共同的生活习性:对于同一个岛上的任意两个生物,他们有且仅有一 ...

  8. 模态运行EXE程序

    function ExecShowModal(APath: PChar; ACmdShow: Integer; ATimeout: Longword): Integer; var vStartupIn ...

  9. BAT 批处理实现循环备份N天文件夹

    @echo off set today=%date:~0,4%%date:~5,2%%date:~8,2% xcopy  /E /I E:\aaa e:\test\%today% for /f &qu ...

  10. 【HDOJ】3419 The Three Groups

    记忆化搜索. /* 3419 */ #include <cstdio> #include <cstring> #include <cstdlib> #define ...