これを行うための最良かつ最もクリーンな方法は何ですか?具体的には、そのクラスで実行するために静的初期化ブロックにいくつかのコードが必要ですが、これをできるだけきれいに見せたいと思います。
6 に答える
読み込み中!=初期化。
クラスを初期化する必要があります(これは、特に静的ブロックが実行されるときです)。
Java言語仕様からの抜粋は次のように述べています。
クラスまたはインターフェースタイプTは、次のいずれかが最初に発生する直前に初期化されます。
- Tはクラスであり、Tのインスタンスが作成されます。
- Tはクラスであり、Tによって宣言された静的メソッドが呼び出されます。
- Tによって宣言された静的フィールドが割り当てられます。
- Tによって宣言された静的フィールドが使用され、フィールドは定数変数ではありません(§4.12.4)。
- Tは最上位クラスであり、T内に字句的にネストされたassertステートメント(§14.10)が実行されます。
クラスClassおよびパッケージjava.lang.reflectで特定のリフレクティブメソッドを呼び出すと、クラスまたはインターフェイスが初期化されます。クラスまたはインターフェイスは、他の状況では初期化されません。
anovstrupのDohは、すでに次のように述べています。。という空の静的関数を作成するだけinit
です。必ずそれを文書化してください...しかし、私は個人的に、整形式のコードのコンテキストでこれのユースケースを見ることができません。
次のコードを使用して、クラスの初期化を強制できます。
//... Foo.class ... //OLD CODE
... forceInit(Foo.class) ... //NEW CODE
/**
* Forces the initialization of the class pertaining to
* the specified <tt>Class</tt> object.
* This method does nothing if the class is already
* initialized prior to invocation.
*
* @param klass the class for which to force initialization
* @return <tt>klass</tt>
*/
public static <T> Class<T> forceInit(Class<T> klass) {
try {
Class.forName(klass.getName(), true, klass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new AssertionError(e); // Can't happen
}
return klass;
}
try
{
Class.forName(class name as string)
}
catch(ClassNotFoundException e)
{
whatever
}
それはそれをする必要があります。
@Longpoke
多分私は何かを誤解しています。クラスがロードされているが静的初期化子が実行されていない例を作成できますか?ロードしたことを印刷するだけの例を次に示します。
package test;
public class TestStatic
{
public static void main(String[] args)
{
try
{
Class.forName("test.Static");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
次の静的クラスがロードされている場合:
package test;
public class Static
{
static
{
System.out.println("Static Initializer ran...");
}
}
リストした条件が満たされるまで静的初期化子が実行されない場合、テストを実行するとなぜこのprintlnが実行されるのですか?それは私が満たしているあなたのリストされた条件のどれですか?
クラス間の目に見えない依存関係は良い考えではありません。静的初期化ブロックのコードを静的メソッドに移動し、依存クラスで直接呼び出すことをお勧めします。静的初期化ブロックは、新しく作成された静的メソッドを呼び出すように書き直すことができます。
1つの解決策は、静的メソッドを呼び出すことです。
public class A {
static { DebugUtils.FLAG_TEST_USER = true; }
static void init() {}
}
次に、を呼び出しA.init()
て初期化を強制します。
ただし、これを行うのはコードの臭いです。静的コードをシングルトンオブジェクトの標準コンストラクターに置き換えることを検討してください。
クラス内の何かを静的に初期化する必要がある場合は、それに依存するクライアントクラスが存在する必要があることを意味します。
クライアントが1つある場合、または初期化ブロックの自然なホームと呼ぼうとすると、そこで初期化するのが最もクリーンだと思います。
多くの同等のクライアントの場合、これらのクラスから、他のクラスの静的な初期化が成功したことを確認することをお勧めします。次に、結合が文書化され、最初のクライアントが必要とする前にクラスが常に初期化されることが確実になります。