Java基础知识的澄清?

时间:2009-12-12 12:31:46

标签: java

class test {

    test() {
        System.out.println("Constructor");
    }

    {
        System.out.println("Hai");
    }

}

public class sample {

    public static void main(String [] a) {
        test t = new test();        
    }

}

在上面的代码中为什么大括号((即“Hai”)中给出的语句在构造函数执行之前被打印。

4 个答案:

答案 0 :(得分:34)

让我们用一个更明确的例子来表达:

public class Test {

    static {
         System.out.println("static initializer");
    }

    {
         System.out.println("instance initializer");
    }

    public Test() {
         System.out.println("constructor");
    }

}

并按如下方式进行测试:

public class Main {

    public static void main(String[] args) {
        Test test1 = new Test();
        Test test2 = new Test();
    }

}

输出:

static initializer
instance initializer
constructor
instance initializer
constructor

静态初始化程序在运行时仅执行一次,特别是在加载类时。实例初始值设定项在构造函数之前的每个实例化期间执行。

您可以拥有多个,并且它们将按照编码中的顺序执行。

实例初始化程序的主要好处是无论您使用哪种构造函数,它们都会被执行。它们适用于每一个,因此您不需要在所有这些上复制常见的初始化。

静态初始化器的主要好处是它们在类加载期间只执行一次。一个众所周知的现实世界的例子是JDBC驱动程序。当你这样做

 Class.forName("com.example.jdbc.Driver");

只执行static初始化程序,然后任何(正常的)JDBC驱动程序将在DriverManager中注册自己,如下所示

 static {
      DriverManager.registerDriver(new com.example.jdbc.Driver());
 }

这样DriverManager可以在getConnection()期间找到正确的JDBC驱动程序。

答案 1 :(得分:6)

是。这是一个instance initializer。它会在实例化后立即运行。

答案 2 :(得分:3)

  

在上面的代码中,为什么在执行构造函数之前,大括号((即“Hai”)中给出的语句是Printed。

因为这是12.5 Creation of New Class InstancesJava Language Specification部分所述的预期行为:)

  

在引用之前   创建的对象作为返回   结果,指示的构造函数是   处理以初始化新对象   使用以下程序:

     
      
  1. 将构造函数的参数分配给新创建的参数   此构造函数的变量   调用。
  2.   
  3. 如果此构造函数以显式构造函数调用开头   同一个类中的另一个构造函数   (使用this),然后评估   参数和进程构造函数   使用这些递归调用   同样的五个步骤。如果那个构造函数   然后,调用突然完成   这个程序突然完成了   同样的原因;否则,继续   步骤5。
  4.   
  5. 此构造函数不以显式构造函数开头   调用另一个构造函数   同一个班级(使用this)。如果这   构造函数是用于除了之外的类   Object,然后这个构造函数会   以明示或暗示开头   调用超类构造函数   (使用super)。评估   超类的参数和过程   构造函数调用递归   使用这五个相同的步骤。如果说   构造函数调用完成   突然,然后这个程序   为此突然完成   原因。否则,继续步骤   4。
  6.   
  7. 执行实例初始值设定项和实例变量初始值设定项   这个类,分配值   实例变量初始化器   相应的实例变量,in   他们的从左到右的顺序   在源代码中以文本形式出现   为了上课。如果执行任何   这些初始化器导致了   例外,然后没有进一步   初始化程序已处理完毕   程序突然完成   同样的例外。否则,继续   与第5步。(在一些早期   实现,编译器   错误地省略了代码   如果字段初始化字段   初始化表达式是一个常量   值等于的表达式   默认的初始化值   它的类型。)
  8.   
  9. 执行此构造函数的其余部分。如果执行   突然完成,然后这个   程序突然完成   同样的道理。否则,这个程序   正常完成。
  10.   

有关...实例初始值设定项的详细信息,请参阅8.6 Instance Initializers部分。

答案 3 :(得分:2)

类中的大括号引入了一个实例初始化器(在Java 1.1中引入)。它们的处理方式与指定作为声明一部分的字段的代码相同。所以以下是等价的:

 private final Thing x = new Thing();

 private final Thing x;
 {
     x = new Thing();
 }

代码在调用超级构造函数后立即由构造函数执行。因此,假设没有其他初始化,代码可以作为构造函数的一部分等效地编写:

 private final Thing x;
 public MyCLass() {
     super(); // Often implicit.
     x = new Thing();
 }

位于相同位置的大括号前面有static关键字和静态初始化程序,在初始化类时执行一次,而不是基于每个实例执行。