在Java中,main方法之后的那些语句的初始化顺序是什么

时间:2017-04-01 08:49:07

标签: java initialization

我了解到初始化顺序的原则是:

  1. 超级优先(本案未在此讨论)
  2. 出现顺序的静态变量声明和静态初始化块
  3. 出现顺序的实例变量声明和静态初始化块
  4. 构造函数
  5. 但是我仍然对这段代码的输出感到困惑:

    public class Test1 {
    
        static {
            add(2);
        }
    
        static void add (int num) {
            System.out.println(num + " ");
        }
    
        public Test1() {
            add(5);
            System.out.println("Constructor!");
        }
    
        static {
            add(4);
        }
    
        {
            add(6);
        }
    
        static {
            new Test1();
        }
    
        {
            add(8);
        }
    
        public static void main(String[] args) {
            System.out.println("Main method!");
            add(10);
        }
    
        {
            add(11);
        }
        static {
            add(12);
        }
    }
    

    结果是:

    2 
    4 
    6 
    8 
    11 
    5 
    Constructor!
    12
    Main method!
    10 
    

    如果没有添加(10)的陈述;加(11);加(12);我完全可以理解。你能解释一下这三个陈述的初始化顺序吗?

5 个答案:

答案 0 :(得分:7)

1)没有如下名称的块称为“实例初始化程序”,只有在创建新对象时才会调用它,如DefaultConstructor或noArg构造函数。

{
    add(11);
}

2)在上面的代码中,您有静态阻止首先在类加载时调用),实例初始化程序创建对象时调用的内容),显式DefaultConstructor 在创建对象时调用,但始终记住Instance初始化程序优先级)和最后一个Main方法

3)现在让我们分析你的代码,

第一个电话:

static 
{
   add(2); //print 2
}

第二次致电:

static {
        add(4); // print 4
}

第三次致电:

static {
    new Test1(); 
    // Here Object is getting created so all Instance Initialzer will be called first in a sequential manner.
}

第4次致电:

{
    add(6); // print 6
}

第五次致电:

{
    add(8);  // print 8
}

第6次致电:

{
    add(11);   // print 11
}

第7次调用:在Instance Initializer之后,将调用Explicit Default Constructor。

public Test1() {
    add(5);    // print 5
    System.out.println("Constructor!");   // print Constructor!
}

第8次调用:再次调用最后一个静态块。

static {
    add(12);   // print 12
}

第9次调用:最后将调用main方法

public static void main(String[] args) {
    System.out.println("Main method!");  // print Main method!
    add(10); // print 10
}

答案 1 :(得分:6)

静态初始化程序是第一个,所以你得到

2 
4

但是在下一个静态初始化程序中,你调用了一个新的Test1.class实例,因此触发了实例初始化程序,在它们之后触发构造函数,然后得到:

6 
8 
11 
5 
Constructor!

之后调用其余的静态初始值设定项。这样:

12

最后一个是主要方法:

Main method!
10 

答案 2 :(得分:1)

我觉得你很困惑因为(12)之前(主要方法 - 10)

发生这种情况是因为在最后但其他初始化顺序调用的main方法是明确的

答案 3 :(得分:1)

在Java中,对于一个类所有静态初始值设定项在所有构造函数之前按顺序执行(从上到下)。 {}中的术语被添加到构造函数中,这些不是静态初始值设定项(请参阅http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html)。

因此,Test1的实例1:

static {
    add(2);
}
...
static {
    add(4);
}

然后,在静态块内部有一个Test1的构造函数。它被调用,因此实例成员被初始化,因为之前的静态初始化程序已被调用:

{
    add(6);
}
...
{
    add(8);
}
...
{
    add(11);
}

之后,将调用构造函数中的下一个操作:

add(5);

然后我们在第一个实例中返回以调用最后一个静态initiazer:

static {
    add(12);
}

最后,如果完全初始化了类,那么调用main方法:

public static void main(String[] args) {
    System.out.println("Main method!");
    add(10);
}

所以,输出:

2 
4 
6 
8 
11 
5 
Constructor!
12
Main method!
10 

答案 4 :(得分:1)

无论@DontPanic的答案是否正确,我要强调的要点是源代码中代码块的顺序(从上到下)也很重要,你可以看一下来自Java doc。{/ 3>的here

  

一个类可以有任意数量的静态初始化块,以及它们   可以出现在类体中的任何位置。运行时系统保证   静态初始化块按它们的顺序调用   出现在源代码中。