373

私の質問は、 static キーワードの特定の使用法に関するものです。キーワードを使用staticして、どの関数にも属さないクラス内のコード ブロックをカバーすることができます。たとえば、次のコードはコンパイルされます。

public class Test {
    private static final int a;    
    static {
        a = 5;
        doSomething(a);
    }
    private static int doSomething(int x) {
        return (x+5);
    }
}

キーワードを削除するstaticと、変数afinal. finalただし、キーワードとキーワードの両方を削除しstaticてコンパイルすることは可能です。

両方の点で私を混乱させます。どのメソッドにも属さないコード セクションを作成するにはどうすればよいですか? それをどのように呼び出すことができますか?一般的に、この使用の目的は何ですか? または、これに関するドキュメントはどこにありますか?

4

8 に答える 8

423

static 修飾子を持つコード ブロックは、クラス初期化子を意味します。static 修飾子がない場合、コード ブロックはインスタンス初期化子になります。

クラス初期化子は、クラスがロードされるとき (実際には、解決されたときですが、それは技術的なことです) に定義された順序で実行されます (単純な変数初期化子と同じようにトップダウン)。

インスタンス初期化子は、クラスのインスタンス化時に定義された順序で、コンストラクター コードが実行される直前、スーパー コンストラクターの呼び出しの直後に実行されます。

staticから削除するint aと、静的初期化ブロックからアクセスできないインスタンス変数になります。これは、「非静的変数 a は静的コンテキストから参照できません」というエラーでコンパイルに失敗します。

static初期化ブロックからも削除すると、インスタンス初期化子になりint a、構築時に初期化されます。

于 2008-12-02T20:35:47.500 に答える
183

うーん!静的初期化子とは何ですか?

静的初期化子は、static {}Java クラス内のコードのブロックであり、コンストラクターまたはメイン メソッドが呼び出される前に 1 回だけ実行されます。

わかった!もっと教えて...

  • static { ... }任意の Java クラス内のコードのブロックです。クラスが呼び出されたときに仮想マシンによって実行されます。
  • returnサポートされているステートメントはありません。
  • 引数はサポートされていません。
  • いいえthis、またはsuperサポートされています。

うーん、どこで使えますか?

大丈夫だと思う場所ならどこでも使用できます:)とてもシンプルです。しかし、ほとんどの場合、データベース接続、API 初期化、ロギングなどを行うときに使用されます。

吠えるだけじゃない!例はどこですか?

package com.example.learnjava;

import java.util.ArrayList;

public class Fruit {

    static {
        System.out.println("Inside Static Initializer.");

        // fruits array
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Orange");
        fruits.add("Pear");

        // print fruits
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
        System.out.println("End Static Initializer.\n");
    }

    public static void main(String[] args) {
        System.out.println("Inside Main Method.");
    }
}

出力???

内部静的初期化子。

アップル

オレンジ

静的初期化子を終了します。

Main メソッドの内部。

お役に立てれば!

于 2015-03-24T05:10:18.890 に答える
61

staticブロックは「静的初期化子」です。

クラスがロードされると自動的に呼び出され、それを呼び出す他の方法はありません (リフレクション経由であっても)。

個人的には、JNI コードを記述するときにのみ使用しました。

class JNIGlue {
    static {
        System.loadLibrary("foo");
    }
}
于 2008-12-02T20:33:34.320 に答える
51

これはhttp://www.programcreek.com/2011/10/java-class-instance-initializers/から直接です

1. 執行命令

次のクラスを見てください。どちらが最初に実行されるか知っていますか?

public class Foo {
 
    //instance variable initializer
    String s = "abc";
 
    //constructor
    public Foo() {
        System.out.println("constructor called");
    }
 
    //static initializer
    static {
        System.out.println("static initializer called");
    }
 
    //instance initializer
    {
        System.out.println("instance initializer called");
    }
 
    public static void main(String[] args) {
        new Foo();
        new Foo();
    }
}

出力:

呼び出された静的イニシャライザ

呼び出されたインスタンス初期化子

呼び出されたコンストラクター

呼び出されたインスタンス初期化子

呼び出されたコンストラクター

2. Java インスタンス初期化子はどのように機能しますか?

上記のインスタンス初期化子には、println ステートメントが含まれています。それがどのように機能するかを理解するために、変数割り当てステートメントとして扱うことができますb = 0。これにより、より明確に理解することができます。

それ以外の

int b = 0、あなたは書くことができます

int b;
b = 0;

したがって、インスタンス初期化子とインスタンス変数初期化子はほとんど同じです。

3. インスタンス初期化子が役立つのはいつですか?

インスタンス初期化子の使用はめったにありませんが、次の場合はインスタンス変数初期化子の代わりとして便利です。

  1. 初期化コードは例外を処理する必要があります
  2. インスタンス変数初期化子で表現できない計算を実行します。

もちろん、そのようなコードはコンストラクターで記述できます。ただし、クラスに複数のコンストラクターがある場合は、コンストラクターごとにコードを繰り返す必要があります。

インスタンス初期化子を使用すると、コードを 1 回記述するだけで、オブジェクトの作成に使用されたコンストラクターに関係なく実行されます。(これは単なる概念であり、あまり使用されていないと思います。)

インスタンス初期化子が役立つもう 1 つのケースは、コンストラクターをまったく宣言できない匿名の内部クラスです。(これはロギング機能を配置するのに適した場所でしょうか?)

デルハインのおかげです。

また、インターフェース [1] を実装する Anonymous クラスにはコンストラクターがないことに注意してください。したがって、構築時にあらゆる種類の式を実行するには、インスタンス初期化子が必要です。

于 2015-05-22T05:27:00.863 に答える
13

「final」は、オブジェクト初期化コードの終了前に変数を初期化する必要があることを保証します。同様に、「静的最終」は、変数がクラス初期化コードの終わりまでに初期化されることを保証します。初期化コードから「静的」を省略すると、オブジェクト初期化コードになります。したがって、変数はその保証を満たさなくなります。

于 2008-12-02T20:36:31.103 に答える
9

プログラムのどこかで呼び出す必要がある静的ブロックにコードを記述しないでください。コードの目的が呼び出されることである場合は、それをメソッドに配置する必要があります。

クラスのロード時に静的変数を初期化する静的初期化子ブロックを作成できますが、このコードはより複雑になる可能性があります。

静的初期化ブロックは、名前も引数も戻り値の型もないメソッドのように見えます。あなたはそれを決して呼ばないので、名前は必要ありません。これが呼び出されるのは、仮想マシンがクラスをロードするときだけです。

于 2008-12-02T20:35:20.387 に答える
4

静的コード ブロックを使用して、(オブジェクト変数ではなく) クラス変数をインスタンス化または初期化できます。したがって、"a" を静的に宣言するということは、それがすべての Test オブジェクトによって共有される 1 つのみであることを意味し、静的コード ブロックは "a" を初期化するのは、Test クラスが最初に読み込まれたときに 1 回だけです (作成された Test オブジェクトの数に関係なく)。

于 2008-12-02T20:34:43.260 に答える