由阿里巴巴一道笔试题看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之间.当然用户可能 ...
随机推荐
- C#中Predicate的一点理解
本人喜欢代码看起来比较优雅,而C#真的是一种很优雅的语言.比如我们New List<string> StrList; 如果我们想查找StrList,可以使用C#提供的 StrList.Fi ...
- Java 可变参数
java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理.注意:可变参数必须位于最后一项.当可变参数个数多余一个时,必将有一个不是最后一项,所以只支持 ...
- Java学习----你可以知道对象的工作结果(获取方法的返回值)
1.写返回类型 2.return 返回值 3.定义变量接受返回值 public class App2 { public String [] print(String msg, int num) { f ...
- Linux mail 命令使用
linux mail 命令参数: 使用mail发邮件时,必须先将sendmail服务启动. mail –s “邮件主题” –c”抄送地址” –b “密送地址” -- -f 发送人邮件地址 –F 发件人 ...
- aix7安装was7、打补丁、更改访问端口、手动启动was、配置was7、部署项目
1:准备工作 首先了解下我们下面即将用到的aix命令,以及安装包.补丁安装工具.补丁 was7的安装包以及补丁工具都是压缩包形式并且以.tar.gz结尾的 安装包在800MB左右,通常为****_w ...
- Ajax实现的长轮询不阻塞同一时间内页面的其他Ajax请求(同域请求)
最近要做一个来电的弹屏功能,利用OM 系统的接口,OM系统发送请求到接口程序,分析数据添加到mysql数据库中,然后把最新的数据id 跟今日来电的总的数量存储到memcache 中.弹屏程序根据读取的 ...
- Vim及VimScript资料总结《转载》
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] Vim教程 入门 Vim 实用技术 Learning the vi and Vim Editors A Byte of ...
- CentOS 6.3 配置FTP
一.FTP的安装 .检测是否安装了FTP:[root@localhost ~]# rpm -q vsftpd 如果安装了会显示版本信息: [root@localhost ~]# vsftpd-2.0. ...
- ios的Ping++支付接入步骤-b
1. Client 发送支付要素给 Server 2. Server 发送支付请求并将返回的支付凭据传给 Client 3. Client 调起支付控件完成支付 4. 渠道同步返回支付结果给 Clie ...
- IBM Websphere 说明文档
http://pic.dhe.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=%2Fcom.ibm.websphere.nd.doc%2Finfo%2F ...