2

あいまいなタイトルで申し訳ありません。何が問題なのか完全にはわかりません。

バックグラウンド

つまり、特定の基本クラスの子クラスは、基本クラスの静的メソッドを隠して、3 つの特定の静的メソッドを定義する必要があります。実装記述クラスは、初期化時にこれをチェックします。アプリケーションの実行中はランダムに見えますが、初期化中にメソッドを適切に再実装していないことを示す実行時例外が発生します。しかし、これが発生するのはまれであり、メソッドの順序を単純にシャッフルするだけで、別の長い間修正されます。

コード

したがって、3 つのクラス: Base、Derived、および AlgImplementation クラス:

AlgImplementation コンストラクター:

/* verifying that the extending class has implemented these methods */
        if (this.getAlgorithmClassName() == null) {
            throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassName() method from as specified.");
        }
        if (this.getAlgorithmClassDescription() == null) {
            throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassDescription() method from as specified.");
        }
        if (this.getAlgorithmClassAnalyticLevel() == null) {
            throw new IllegalArgumentException("The Algorithm Class of this algorithm has not re-implemented the getAlgorithmClassAnalyticLevel() method from as specified.");
        }

ここで問題が発生します。これらのチェックの 1 つが失敗します。上記の 1 つ以上から IllegalArgumentException を取得します。派生クラス内で実装の順序を単純に移動して、そのコードを強制的に再構築すると、問題なく動作します。

基本クラスと派生クラスはどちらも同じ単純な静的メソッドを持ちますが、それらが返す静的フィールドの定義は異なります。

class Derived extends Base {
public static AnalyticLevel getAlgorithmClassAnalyticLevel()
    {
        return ANALYTIC_LEVEL;
    }

    public static String getAlgorithmClassName()
    {
        return NAME;
    }

    public static String getAlgorithmClassDescription()
    {
        return DESCRIPTION;
    }
 }

上記のフィールドはすべて、null 以外の static final String です。

ここで、Derived クラスで static final AlgImplementation フィールドを宣言します。

最後に、この AlgImplementation インスタンスが各静的メソッド クラスに対してこれを行うということを知っておく必要があると思います。

public String getAlgorithmClassName() {
        String className = "";
        try {
            className = (String)algorithmClass.getDeclaredMethod("getAlgorithmClassName", new Class<?>[0]).invoke(null, new Object[0]);
        } catch (Exception e) {
            throw new UnsupportedOperationException("Required static method getAlgorithmClassName() not implemented on "+this.getClass().getName());
        }
        return className;
    }

ついに

したがって、私の質問は次のとおりです。これらのメソッドが実際に宣言されている場合、派生メソッドのチェックはどのように失敗するのでしょうか? 定義されているまさにそのクラスを参照する静的な AlgImplementation フィールドを宣言することに問題はありますか (コンパイルの問題の奇妙な順序などを引き起こします)?

エラーは、Derived クラスの初期化中、具体的には静的 AlgImplementation フィールドを初期化する行にあるため、Derived クラス自体でそれを行うと問題が発生する可能性があると思います。

4

2 に答える 2

1

この問題は、クラスの static final フィールドの初期化順序が原因であると思われます。クラスの初期化中にリフレクションを使用すると、クラスが完全に初期化される前にクラスにアクセスできます。派生クラスの場合、次のものがあります。

public static final String NAME;
static {
    NAME = "some name";
}

public static final AlgImplementation derivedAlg =
    new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");

次に、AlgImplementation は、初期化された後に NAME 定数をチェックし、「何らかの名前」文字列を読み取ります。順序を逆にすると:

public static final AlgImplementation derivedAlg =
    new AlgImplementation("xyz", Derived.class, "Our XYZ derived class", "");

public static final String NAME;
static {
    NAME = "some name";
}

AlgImplementation は、割り当てられる前に定数を読み取り、null代わりに読み取ります。

NAME が次のようなコンパイル時の定数によって直接割り当てられている場合、これが発生する可能性があるかどうかはわかりません。

public static final String NAME = "some name";

それが問題を防ぐと思いましたが、そうではないかもしれません。「メソッドの順序をシャッフルすると、しばらくの間修正される」というあなたの声明は、問題が初期化順序によるものであるという考えを裏付けています。derivedAlg他のすべての定数の後にフィールドを移動して、最後に初期化されるようにすることをお勧めします。

于 2013-10-31T15:57:27.110 に答える
0

静的メソッドはクラス階層に参加しません。常にどちらかstaticMethod()またはClass.staticMethod()代わりに使用する必要があります。

于 2013-10-31T15:19:12.323 に答える