一道简单有趣的java题:输出顺序的问题

这道题来自stackoverflow。

问题描述:

有如下代码,求其输出内容。

1234567891011121314
public class Test{    public int a = 10;    Test(){System.out.println("1");}    {System.out.println("2");}    static{System.out.println("3");}    public static void main(String args[])    {        new Test();    }}

分析

作为静态区段的语句,容易知道,3 是会最先出现的。容易弄错的一点是 到底是 1 和 2 的出现顺序。

我们可以参考字节码来分析。在 eclipse 中使用 ASM bytecode 插件,得到相应的字节码:

123456789101112131415161718192021222324252627282930
// class version 50.0 (50)  // access flags 0x21  public class Test {  // compiled from: Test.java    static <clinit>() : void    GETSTATIC System.out : PrintStream    LDC "3"    INVOKEVIRTUAL PrintStream.println(String) : void    RETURN  <init>() : void    ALOAD 0: this    INVOKESPECIAL Object.<init>() : void    ALOAD 0: this    BIPUSH 10    PUTFIELD Test.a : int    GETSTATIC System.out : PrintStream    LDC "2"    INVOKEVIRTUAL PrintStream.println(String) : void    GETSTATIC System.out : PrintStream    LDC "1"    INVOKEVIRTUAL PrintStream.println(String) : void    RETURN  public static main(String[]) : void    NEW Test    INVOKESPECIAL Test.<init>() : void    RETURN}

正如我们所想,3 是被放在类构造方法中,这是类的初始化函数,固然在类的初始化时出现。

而在构造方法中先出现 2,之后才是 1。问题的核心集中到对象构造方法的指令顺序问题。实际上,在对象构造方法中,会先执行一些隐性的指令,比如父类的构造方法、{}区段的内容等,然后在执行显性的构造方法中的指令:

    Java 编译时,对象构造方法里先嵌入隐式的指令,完毕之后,再执行 Java 源代码中显示的代码。

2.那些隐式的指令,包括父类的构造方法、变量的初始化、{}区段里的内容,并严格按照这个顺序嵌入到对象的构造方法中。

http://biaobiaoqi.github.com/blog/2013/09/08/strange-behavior-using-braces-in-java/Creative Commons BY-NC-ND 3.0

接受失败也等于给了自己从零开始的机会,

一道简单有趣的java题:输出顺序的问题

相关文章:

你感兴趣的文章:

标签云: