121

コードをコンストラクター、メソッド、または初期化ブロックに入れることができます。初期化ブロックの用途は何ですか? すべてのJavaプログラムがそれを持っている必要がありますか?

4

10 に答える 10

211

まず、初期化ブロックには2つのタイプがあります。

  • インスタンス初期化ブロック、および
  • 静的初期化ブロック

このコードは、それらの使用法とそれらが実行される順序を示す必要があります。

public class Test {

    static int staticVariable;
    int nonStaticVariable;        

    // Static initialization block:
    // Runs once (when the class is initialized)
    static {
        System.out.println("Static initalization.");
        staticVariable = 5;
    }

    // Instance initialization block:
    // Runs each time you instantiate an object
    {
        System.out.println("Instance initialization.");
        nonStaticVariable = 7;
    }

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

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

プリント:

Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.

インスタンスの初期化ブロックは、使用されているコンストラクターに関係なくコードを実行する場合、または匿名クラスのインスタンスの初期化を行う場合に役立ちます。

于 2010-10-21T12:46:17.977 に答える
107

@aioobeの回答に追加したい

実行順序:

  1. スーパークラスの静的初期化ブロック

  2. クラスの静的初期化ブロック

  3. スーパークラスのインスタンス初期化ブロック

  4. スーパークラスのコンストラクタ

  5. クラスのインスタンス初期化ブロック

  6. クラスのコンストラクタ。

留意すべき追加のポイントがいくつかあります(ポイント1は@aioobeの回答の繰り返しです):

  1. 静的初期化ブロックのコードは、クラスのロード時 (つまり、クラスのロードごとに 1 回だけ)、クラスのインスタンスが構築される前、および静的メソッドが呼び出される前に実行されます。

  2. インスタンス初期化ブロックは、Java コンパイラによって、クラスが持つすべてのコンストラクタに実際にコピーされます。したがって、インスタンス初期化ブロックのコードがコンストラクターのコードの直前に実行されるたびに。

于 2013-03-14T15:36:33.030 に答える
12

さらにいくつかのポイントを追加するaioobeによる素敵な答え

public class StaticTest extends parent {
    static {
        System.out.println("inside satic block");
    }

    StaticTest() {
        System.out.println("inside constructor of child");
    }

    {
        System.out.println("inside initialization block");
    }

    public static void main(String[] args) {
        new StaticTest();
        new StaticTest();
        System.out.println("inside main");
    }
}

class parent {
    static {
        System.out.println("inside parent Static block");
    }
    {
        System.out.println("inside parent initialisation block");
    }

    parent() {
        System.out.println("inside parent constructor");
    }
}

これは与える

inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main

明白なことを述べているようなものですが、もう少し明確に見えます。

于 2014-07-03T06:36:13.833 に答える
0

質問は完全には明確ではありませんが、オブジェクトのデータを初期化する方法について簡単に説明します。オブジェクトのリストを保持するクラスAがあるとします。

1)フィールド宣言に初期値を入力します。

class A {
    private List<Object> data = new ArrayList<Object>();
}

2)コンストラクターで初期値を割り当てます。

class A {
    private List<Object> data;
    public A() {
        data = new ArrayList<Object>();
    }
}

これらは両方とも、コンストラクター引数として「データ」を渡したくないことを前提としています。

上記のようにオーバーロードされたコンストラクターを内部データと混合すると、状況が少し複雑になります。検討:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        data = new ArrayList<Object>();
        name = "Default name";
        userFriendlyName = "Default user friendly name";
    }

    public B(String name) {
        data = new ArrayList<Object>();
        this.name = name;
        userFriendlyName = name;
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

繰り返されるコードがたくさんあることに注意してください。これは、コンストラクターが相互に呼び出すようにすることで修正できます。または、各コンストラクターが呼び出すプライベート初期化メソッドを使用することもできます。

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        this("Default name", "Default user friendly name");
    }

    public B(String name) {
        this(name, name);
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

また

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        init("Default name", "Default user friendly name");
    }

    public B(String name) {
        init(name, name);
    }

    public B(String name, String userFriendlyName) {
        init(name, userFriendlyName);
    }

    private void init(String _name, String _userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

2つは(多かれ少なかれ)同等です。

オブジェクトのデータを初期化する方法についてのヒントが得られることを願っています。静的初期化ブロックについては、現時点ではおそらく少し進んでいるため、ここでは説明しません。

編集:イニシャライザーブロックは比較的高度な概念であるため、「イニシャライザーブロックはどのように機能するか」ではなく、「インスタンス変数をどのように初期化するか」としてあなたの質問を解釈しました。質問のトーンから、あなたが質問しているようです。より単純な概念。私は間違っている可能性があります。

于 2010-10-21T12:45:56.683 に答える
0
public class StaticInitializationBlock {

    static int staticVariable;
    int instanceVariable;

    // Static Initialization Block
    static { 
        System.out.println("Static block");
        staticVariable = 5;

    }

    // Instance Initialization Block
    { 

        instanceVariable = 7;
        System.out.println("Instance Block");
        System.out.println(staticVariable);
        System.out.println(instanceVariable);

        staticVariable = 10;
    }


    public StaticInitializationBlock() { 

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

    public static void main(String[] args) {
        new StaticInitializationBlock();
        new StaticInitializationBlock();
    }

}

出力:

Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor
于 2015-02-05T23:30:33.853 に答える
0

初期化ブロックは、クラスが初期化されるたびに、コンストラクターが呼び出される前に実行されます。それらは通常、中括弧内のコンストラクターの上に配置されます。それらをクラスに含める必要はまったくありません。

これらは通常、参照変数を初期化するために使用されます。このページは良い説明を提供します

于 2010-10-21T12:39:58.723 に答える