由阿里巴巴一道笔试题看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之间.当然用户可能 ...
随机推荐
- Linux系统、版本、CPU、内存查看、硬盘空间
查看系统版本:lsb_release -a [root@localhost /]# lsb_release -a LSB Version: :core-4.0-amd64:core-4.0-no ...
- 小记搭建WAPM运行ThinkPHP时所需要的配置
最近因为项目而接触到了Thinkphp,正在上手中.但昨天遇到几个问题,一下子牵连出之前搭建WAPM(windows+apache+PHP+MySQL)遗留的配置问题. aphache\conf目录下 ...
- srand((double)microtime()*1000000)
分为4个步骤1:执行microtime(),获取当前的微秒数 2:把获取的微秒数转换为double类型 3:再用转换后的数字去乘以1000000 4:给随机数发生器播种,播种数为第三步得出的结果 ra ...
- 在MAC下 Python+Django+mysql配置
今天在搭建Django+mysql环境的时候遇到了一点问题,记录下来. 安装环境:OS X 10.10操作系统,Python 2.7. MySQLdb其实包含在MySQL-python包中,因此无论下 ...
- 常用排序算法集合-C实现
之前熟悉C的时候写着玩的,就当做笔记用吧: #include<stdio.h> #include<stdlib.h> #include<string.h> #inc ...
- 将数据库字段从float修改为decimal
decimal(6,2) 可以表示0000.00~9999.99 alter table test modify aaa decimal(6,2); 则表里所有大于10000的数会被设置为9999.9 ...
- [BZOJ 2724] [Violet 6] 蒲公英 【分块】
题目链接:BZOJ - 2724 题目分析 这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便 ...
- IHS怎么通过80端口连接WAS——<转>
IHS如何通过80端口连接WAS? 经常看到有朋友问这个问题,所以简单总结一下基本步骤: IHS和WAS之间是通过Plugin来实现的,一般的Plugins和IHS安装在同一物理机器上,WAS安装 ...
- Blue Jeans(串)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10083 Accepted: 4262 Description The ...
- 安装Maven、nexus
一.软件包版本 jdk:jdk1.7.0_79 maven:apache-maven-3.3.3-bin.tar.gz nexus:nexus-webapp-2.8.0-05.war 二.安装mave ...