2013-09-16 78 views
15

我这下面的一段代码:为什么变量在调用构造函数之前被初始化?

public abstract class UCMService{ 
    private String service;  

    protected DataMap dataMap = new DataMap(); 

    protected class DataMap extends HashMap<String,String> { 

     private static final long serialVersionUID = 4014308857539190977L; 

     public DataMap(){ 
      System.out.println("11111"); 
      put("IdcService",service); 
     } 
    } 

    public UCMService(String service){ 
     System.out.println("2222"); 
     this.service = service; 
    } 
} 

现在,在控制台System.out.printlnDataMap的构造函数的UCMService的构造函数之前执行。

我想知道为什么会发生。

回答

31

这是因为在编译时,编译器每次都在声明的地方做初始化移动到你的类的每一个构造。所以UCMService类的构造有效地编译:

public UCMService(String service){ 
    super(); // First compiler adds a super() to chain to super class constructor 
    dataMap = new DataMap(); // Compiler moves the initialization here (right after `super()`) 
    System.out.println("2222"); 
    this.service = service; 
} 

因此,很明显DataMap()构造函数UCMService类的print语句之前执行。同样,如果您的UCMService类中还有其他构造函数,则初始化将移至所有这些构造函数。


让我们看一个简单的类的字节码:

class Demo { 
    private String str = "rohit"; 

    Demo() { 
     System.out.println("Hello"); 
    } 
} 

编译这个类,并执行命令 - javap -c Demo。你会看到构造函数的后面的字节代码:

Demo(); 
    Code: 
     0: aload_0 
     1: invokespecial #1 // Method java/lang/Object."<init>":()V 
     4: aload_0 
     5: ldc   #2 // String rohit 
     7: putfield  #3 // Field str:Ljava/lang/String; 
     10: getstatic  #4 // Field java/lang/System.out:Ljava/io/PrintStream; 
     13: ldc   #5 // String Hello 
     15: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     18: return 

您可以在第7行看到putfield指令,初始化场str"rohit",这是print语句之前(指令在行15

+0

+1这是一个很好的答案:) – nachokk

+0

啊......这是超级清晰:) –

+0

精彩的解释。非常感谢Rohit。 –

13

简短回答
因为规范是这样说的。

龙回答
这将是很奇怪的构造函数无法使用内联初始化领域。

你希望能够写出

SomeService myService = new SomeService(); 
public MyConstructor() { 
    someService.doSomething(); 
} 
+0

等待,所以有些人告诉我不要在构造函数中工作。我把这个意思是,只在构造函数中赋值变量。 someService.doSomething()算作工作吗? – Kammeot

+1

如果doSomething()实际上做了某些事情,那么是的 - 那是工作。 – nos

+0

@nos如果'doSomething()'没有做什么,那么它应该被重命名为更具描述性的内容。 – AJMansfield

相关问题