名前のないJavaメソッドを呼び出す


100

私は以下のコードを見ていて、少し奇妙なものを見つけました:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

System.outwith "y"はメソッド宣言に属していないので、これはコンパイルエラーになると予想していました{ }。なぜこれが有効なのですか?このコードがどのように呼び出されるか、または呼び出されるべきかわかりません。

これを実行するときにx y c gも生成static { }されますが、シーケンスコンストラクタの前にgetが呼び出されるのはなぜですか?

回答:


148

この:

static {
        System.out.print("x ");
    }

ある静的初期化ブロック、およびクラスがロードされたときに呼び出されます。クラスには必要な数だけそれらを含めることができ、それらは出現順に(上から下に)実行されます。

この:

    {
        System.out.print("y ");
    }

ある初期化ブロック、およびコードは、クラスの各コンストラクタの先頭にコピーされます。したがって、クラスのコンストラクターが多数あり、それらすべてが最初に共通の何かを行う必要がある場合は、コードを1回記述して、このような初期化ブロックに配置するだけで済みます。

したがって、出力は完全に理にかなっています。

以下のようスタンレーは、下記のコメント、参照ブロックinitializaiton記述したOracleチュートリアルのセクションの詳細については、を。


12
すばらしい答えです。初期化ブロックの詳細については、http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Stanley

6
the code is copied into the beginning of each constructor of the class-これは不正解です。コンストラクタがで始まるとしましょう。super("x ");スーパーコンストラクタは、初期化ブロックの前に実行されます。
RokL

3
はい、スーパーコンストラクターへの暗黙的および明示的な呼び出しが最初に実行され、次に初期化ブロックが実行され、残りのコンストラクターコードよりも実行されます。
jlordo

25

メソッドではなく、初期化ブロックです。

 {
    System.out.print("y ");
 }

コンストラクター呼び出しの前に実行されます。ながら

static {
        System.out.print("x ");
       }

ある静的初期化ブロッククラスがクラスローダによってロードされたときに実行されます。

だから、あなたのコード実行時に
静的初期化ブロックが実行されるように、1クラスは、クラスローダによってロードされる
出力:xが印刷され
、初期化ブロックが実行され、その後、constuctorが呼び出されるように、2オブジェクトが作成され
、Yは、Cが続い印刷さ:出力
3。メインメソッドが呼び出され、次にgoメソッドが呼び出されます。
出力:gが出力されます。

最終出力:xycg
これはhttp://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/を助けるかもしれません


@Cthulhu:ありがとう。先週まで有効でしたが、新しいリンクで更新しました。
xyz

16

これは、インスタンス初期化ブロックの後に静的初期化ブロックが続きます

{
    System.out.print("y ");
}

クラスのインスタンスを作成すると呼び出されます。

static {
    System.out.print("x ");
}

クラスローダーによってクラスがロードされるときに呼び出されます。だからあなたがするとき

new Sequence().go();

クラスが読み込まれると実行されstatic {}、次にインスタンス初期化ブロックが実行{}されます。その後、コンストラクターの本体が呼び出され、次に新しく作成されたインスタンスのメソッドが呼び出されます。エルゴ出力x y c g


15
static {
        System.out.print("x ");
    }

ある静的ブロックとクラスローディング中に呼び出されます

{
    System.out.print("y ");
}

ある初期化ブロック

クラスに複数の初期化ブロックを含めることができます。その場合、それらはクラスに出現する順序で実行されます。

クラスに存在する初期化ブロックは、コンストラクタの前に実行されることに注意してください。


10
static {
      System.out.print("x ");
}

(で示されているようにstatic)クラスによって共有される初期化ブロックで、最初に実行されます。

{
        System.out.print("y ");

}

次のクラスのすべてのオブジェクト(コンストラクター)によって共有される初期化ブロックです。

Sequence() {
        System.out.print("c ");
}

クラスの特定のコンストラクターで、3番目に実行されます。インスタンス初期化ブロックは、コンストラクターが実行されるたびに最初に呼び出されます。これが、「y」が「c」の直前に来る理由です。

void go() {
        System.out.print("g ");
}

最後に来る上記のコンストラクタを使用して構築されたオブジェクトに関連付けられた単なるインスタンスメソッドです。


9
{
    System.out.print("y ");
}

これらの種類のブロックはと呼ばれinitializer blockます。のインスタンスを作成するたびに実行されますclass。コンパイル時に、このコードはクラスのすべてのコンストラクターに移動されます。

static initializerブロックの場合のように:-

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

クラスがロードされるときに1回実行されます。通常staticstaticフィールドの初期化で複数のステップが必要な場合は、初期化ブロックを使用します。


6

これは初期化ブロックとして使用され、静的宣言の後に実行されます。シングルトン設計パターンの場合と同様に、(プライベートコンストラクターを使用するのと同じ方法で)他のユーザーがクラスのインスタンスを作成できないようにするために使用できます。


3
static {
    System.out.print("x ");
}

Static blocksJREによってクラスがロードおよび初期化されるとき一度だけ実行されます。

そして、non-staticブロックは、新しいインスタンス作成するたびに呼び出さ、コンストラクタの直前に呼び出されます。

ここで作成しSequenceたのは、non-staticブロックの後に呼び出されたように構築されたインスタンスの1つだけであり、実際に目的のメソッドが呼び出されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.