2

コンストラクター コードのほとんどを に移動することで、この PMD 警告を回避してきましたonInitialize()。しかし、問題 (設計上の欠陥?) を別の場所に移動しているだけなのでしょうか?

つまりonInitialize()、PMD によって認識されない単なる代理コンストラクターですか?

コンストラクターでオーバーライド可能なメソッドを呼び出すときにポップアップするような問題がありますが、これは Wicket 自体がコンストラクターを呼び出すという事実に起因しているようです (正確なソース行を見つけることはできませんがonInitialize()、オーバーライド可能なメソッドが最終的にadd()コンストラクターを呼び出すときに呼び出されます)。

サンプルコードが役立つ場合は、喜んで提供します。

public class PageA extends WebPage {

    protected SomeBean bean;

    public PageA() {
        add(new Label("foo", "bar"));
        bean = new SomeBean();
    }

}

public class PageB extends PageA {

    public PageB() {
        super();
    }

    @Override
    protected void onInitialize() {
        add(new Label("rofl", bean.getSomeText()));
    }
}

onInitializeこれで問題ないと思うかもしれませんが、呼び出しが発生すると思われる場所では発生しません。

add()ページで呼び出す場合のメソッド フローは次のとおりです。

MarkupContainer    add()    
MarkupContainer    addedComponent() 
Page               componentAdded()
MarkupContainer    initialize()
Component          fireInitialize()
Component          onInitialize()

したがって、コンポーネントを に追加するとわかるようにWebPageonInitialize()メソッドが起動されます。これは、 を作成する上記の正常なコードのインスタンスにつながるオーバーライド可能なメソッドNullPointerExceptionです。

これが発生する可能性があるという唯一の警告は、次の JavaDoc ですonInitialize()

注:この呼び出しのタイミングは正確ではありません。{@link Component#onBeforeRender()} の前に呼び出されるという契約があります。

4

3 に答える 3

4

メソッド内からコンテナにコンポーネントを追加するだけであればonInitialized()、この問題は発生しません。ただし、少なくとも組み込みのルールでは、PMD で検証することはできません。

私はそれが設計上の欠陥だとは思わない。設計上の決定です。すべての設計を静的分析ツールと定義済みのルールに基づいて行うことはできません。API の使いやすさも設計の重要な側面であり、設計原則よりも関連性が高い場合もあります。

たとえば、CQS (コマンドとクエリの分離) の原則では、何かを実行する (状態を変更する) メソッドは何も返さないようにし、何かを返すメソッドは副作用 (状態を変更する) を持たないようにする必要があります。

これが厳格なルールである場合、流暢なインターフェイス (オブジェクトの状態を変更し、thisメソッドの連鎖を可能にする return を返すメソッド) を実装できませんでした。Wicket はこれを広範に使用しており (ほとんどすべてのコンポーネント操作メソッドが return を返しますthis)、これが Wicket を楽しく使用できる理由の 1 つです。

PMD は非常に便利なツールです。ただし、ツールのスレーブではなく、ツールのマスターでなければなりません。その警告を問題の可能性として考慮する必要がありますが、設計の選択に自信がある場合は、コードをバイパスするようにマークして満足してください.

于 2011-06-09T12:16:11.173 に答える
1

次のクラスを検討してください。

public class A {

    public A() {
        System.out.println(val().toString());
    }

    protected Integer val() {
        return 0;
    }

}

一見問題ないように見えますが、val()決して返すべきではないと仮定nullします。これは事実です。今BサブクラスA

public class B extends A {

    private final Integer i;

    public B() {
        //super();    //implicit
        i = 1;
    }

    @Override
    protected Integer val() {
        return i;
    }
}

クラスBも一見問題ありません。コンストラクターで初期化されているため、返さiれるval()ことはありません。ただし、インスタンスを作成すると がスローされます。理由がわかりますか?ヒント: 暗黙の場所を見てください。nullfinalBNullPointerExceptionsuper()

i初期化の移動が役立つと思いますか? なぜだめですか?

private final Integer i = 1;

経験則として、非最終クラスのコンストラクターから非プライベート メソッドを呼び出さないでください。実際、この場合、コンパイル エラーが発生することさえあります。ご覧のとおり、この問題は Wicket とは何の関係もなく、初期化を Wicket に移動するのonInitialize()は、そのようなトラップを回避するためです。

于 2011-06-09T11:12:11.940 に答える
0

コンストラクターでオーバーライド可能なメソッドを呼び出すときにポップアップするような問題がありますが、これは Wicket 自体がコンストラクターを呼び出すという事実に起因しているようです (正確なソース行を見つけることはできませんが、onInitialize()、オーバーライド可能なメソッド、コンストラクターで add() を呼び出すと、最終的に呼び出されます)。

onInitialize()呼び出すときに呼び出されるadd(component)メソッドonInitialize()は、追加されるコンポーネントのメソッド ( add メソッドの引数) であり、現在構築しているクラスのメソッドではないと確信しています。そのコンポーネントはすでに完全に構​​築されているため、これで問題ありません。

于 2011-06-09T11:45:20.250 に答える