17

次のコードがあります。

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ます。

なぜそれが起こっているのか疑問に思っていました。

4

2 に答える 2

37

これは、コンパイル時に、コンパイラが宣言の場所で行ったすべての初期化をクラスのすべてのコンストラクターに移動するためです。したがって、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()コンストラクターはクラスのprintステートメントの前に実行されます。UCMService同様に、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"の前にあります(行の命令) 。print15

于 2013-09-16T14:16:40.813 に答える
13

短い答え:
仕様がそう言っているからです。

長い答え:
コンストラクターがインラインで初期化されたフィールドを使用できないのは非常に奇妙です。

書けるようになりたい

SomeService myService = new SomeService();
public MyConstructor() {
    someService.doSomething();
}
于 2013-09-16T14:10:49.563 に答える