A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈郊 中级黑马   /  2012-9-29 19:42  /  2348 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一直以来我我认为这三者的执行顺序是静态代码块、非静态代码块、构造函数。
网上搜了下也都是这么说的。
就像下面这段代码:
Java代码  
1.public class ExA {   
2.    static {   
3.        System.out.println("父类--静态代码块");   
4.    }   
5.  
6.    public ExA() {   
7.        System.out.println("父类--构造函数");   
8.    }   
9.  
10.    {   
11.        System.out.println("父类--非静态代码块");   
12.    }   
13.  
14.    public static void main(String[] args) {   
15.        new ExB();   
16.    }   
17.}   
18.  
19.class ExB extends ExA {   
20.    static {   
21.        System.out.println("子类--静态代码块");   
22.    }   
23.    {   
24.        System.out.println("子类--非静态代码块");   
25.    }   
26.  
27.    public ExB() {   
28.        System.out.println("子类--构造函数");   
29.    }   
30.}  
public class ExA {
static {
  System.out.println("父类--静态代码块");
}
public ExA() {
  System.out.println("父类--构造函数");
}
{
  System.out.println("父类--非静态代码块");
}
public static void main(String[] args) {
  new ExB();
}
}
执行结果
=====
父类--静态代码块
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
可是静态代码块真的会一定在非静态代码块之前执行吗?
下面这段代码
Java代码  
1.public class ExA {   
2.    private static ExA a = new ExA();   
3.    static {   
4.        System.out.println("父类--静态代码块");   
5.    }   
6.  
7.    public ExA() {   
8.        System.out.println("父类--构造函数");   
9.    }   
10.  
11.    {   
12.        System.out.println("父类--非静态代码块");   
13.    }   
14.  
15.    public static void main(String[] args) {   
16.        new ExB();   
17.    }   
18.}   
19.  
20.class ExB extends ExA {   
21.    private static ExB b = new ExB();   
22.    static {   
23.        System.out.println("子类--静态代码块");   
24.    }   
25.    {   
26.        System.out.println("子类--非静态代码块");   
27.    }   
28.  
29.    public ExB() {   
30.        System.out.println("子类--构造函数");   
31.    }   
32.}  
public class ExA {
private static ExA a = new ExA();
static {
  System.out.println("父类--静态代码块");
}
public ExA() {
  System.out.println("父类--构造函数");
}
{
  System.out.println("父类--非静态代码块");
}
public static void main(String[] args) {
  new ExB();
}
}
class ExB extends ExA {
private static ExB b = new ExB();
static {
  System.out.println("子类--静态代码块");
}
{
  System.out.println("子类--非静态代码块");
}
public ExB() {
  System.out.println("子类--构造函数");
}
}
执行结果
=====
父类--非静态代码块
父类--构造函数
父类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
=====
可以发现非静态代码块并不是一定在静态代码块之后执行的。
我认为此时private static ExA a = new ExA()是静态变量。而java里面静态变量与静态代码块是按代码先后顺序执行
。所以就导致非静态代码块在静态代码块之前执行。

评分

参与人数 1技术分 +1 收起 理由
唐志兵 + 1 赞一个!

查看全部评分

2 个回复

倒序浏览
其实说白了 就是先加载类 后加载对象, 而静态部分随着类的加载而加载 优先于主函数
你代码中  把本类对象放到了类的成员位置,作为一个成员变量而存在
使其随着类一起加载,但是对象在类加载的时候尚不存在,为了向前拓宽 该对象的出现时间,所以给他加了一个static。
导致 该对象在加载类的过程中就被一起加载 并初始化了,这个时候的初始化调用了 非静态代码块 和构造函数。
这才出现了非静态出现在静态之前
本质原因还是  对象被作为类的成员随类一起加载了,而静态紧随其后被加载

评分

参与人数 1技术分 +1 收起 理由
唐志兵 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 崔朋朋 于 2012-9-29 23:37 编辑

先加载类字节码,静态部分(静态代码快/静态成员变量)随着类的加载而加载,最后在去执行主函数中的代码(即创建对象引用,初始化成员变量等)。在静态部分是顺序执行的,即按照类文件中的代码编写先后顺序执行。

在你的第二段代码中是先有个静态成员变量并初始化了,对象在初始化的过程中会牵扯到非静态代码块和构造函数的执行,接下来才是静态代码快,在接下来就是主函数的执行了。所以会造成先执行非静态代码块,再执行静态代码块的 “假象”。

其实质还是先执行静态部分,再执行创建对象,初始化成员变量等再非静态部分,只是静态成员变量的初始化牵扯到了非静态部分的执行。

类加载执行顺序:类字节码→静态代码块static{...}/静态成员变量→创建对象引用,初始化成员变量

评分

参与人数 1技术分 +1 收起 理由
王海宇 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马