14

「コンストラクターがオーバーライド可能なメソッドを呼び出す」というメッセージを表示する次のセットアップがあります。私はこれが起こっていることを知っていますが、私の質問は、コードがまだ機能し、メッセージが消えるように修正する方法です.

public interface Foo{
   void doFoo();
}
public class FooImpl implements Foo{
 @Override{
 public void doFoo(){
    //.. Do important code
 }
}
public class Bar{
  private FooImpl fi;
  public Bar(){
    fi = new FooImpl();
    fi.doFoo(); // The message complains about this line
  }
}

ありがとう!

4

4 に答える 4

18

@Vooが言うように、

あなたの質問は、すでに完全に構​​築されたオブジェクトで仮想メソッドを呼び出すことです。構築されたオブジェクトで仮想メソッドを呼び出すことのよく知られた失敗はよく知られていますが、ここでは当てはまりません

有効な Java 2nd Edition、項目 17: 継承のための設計と文書化、またはそれ以外の場合の禁止から:

継承を許可するためにクラスが従わなければならない制限がいくつかあります。コンストラクターは、オーバーライド可能なメソッドを直接または間接的に呼び出してはなりません。この規則に違反すると、プログラムが失敗します。スーパークラス コンストラクターはサブクラス コンストラクターの前に実行されるため、サブクラスのオーバーライド メソッドは、サブクラス コンストラクターが実行される前に呼び出されます。オーバーライドするメソッドが、サブクラス コンストラクターによって実行される初期化に依存している場合、メソッドは期待どおりに動作しません。

オブジェクトの構築中にオーバーライド可能なメソッドを呼び出すと、初期化されていないデータが使用され、実行時例外や予期しない結果が発生する可能性があります。

コンストラクターは、final または private のメソッドのみを呼び出す必要があります

からオブジェクトを作成する必要があるという問題を解決するために、静的ファクトリ メソッドを使用できますBar class

効果的な Java、項目 1: コンストラクターの代わりに静的ファクトリ メソッドを検討する

クライアントがクラス自体のインスタンスを取得できるようにする通常の方法は、パブリック コンストラクターを提供することです。すべてのプログラマーのツールキットに取り入れるべきテクニックがもう 1 つあります。クラスは public static factory メソッドを提供できます。これは、クラスのインスタンスを返す単なる静的メソッドです。

だから、あなたはインターフェースを持っていることに行きます:

public interface Foo {
     void doFoo();
}

そして実装:

public class FooImpl implements Foo {
   @Override
   public void doFoo() {
   //.. Do important code
   }
}

ファクトリ メソッドを使用してクラスを作成するには、次の方法で作業できます。

  • private Foo fiの代わりにインターフェイスを使用して、クラスの変数を定義します。private FooImpl fi具体的な型に対してインターフェイスを使用することは、適切なカプセル化とコードの疎結合の鍵です。

  • デフォルトのコンストラクターをプライベートにして、クラスが外部でインスタンス化されないようにします。

    private Bar() { // インスタンス化を防ぎます }

  • コンストラクターに存在するメソッドをオーバーライドするすべての呼び出しを削除します。

  • 静的ファクトリ メソッドを作成する

最後に、次のBarようなファクトリ メソッドを持つクラスを取得します。

public class Bar {
    private Foo fi;

    private Bar() {// Prevents instantiation
        fi = new FooImpl();
    }

    public static Bar createBar() {
        Bar newBar = new Bar();
        newBar.fi.doFoo(); 

        return newBar;
    }
}

私の上司は次のように述べます。病気を治療できるときが一番です。」!

于 2015-10-08T20:02:24.233 に答える
6

後でそのメソッドをオーバーライドする必要がない場合は、doFoo を final として宣言できます。

public final void doFoo() { }

于 2012-04-26T16:04:45.467 に答える
0

安全ではない可能性があるため、IDE はそれを伝えています。任意の実装または doFoo を提供し、起動時にすべての Bar オブジェクトを別のものにすることができます。これは、ほとんどの場合、設計の選択が不適切に思えます。

コンストラクターで戦略パターンを使用しているようです。コンストラクターで戦略やその他のオーバーライド可能な動作を使用することは賢明ではありません。別の場所で使用してください。

于 2012-04-26T16:05:20.967 に答える
0

表示されるエラーの原因はPMD (そこで「overr」を検索) であり、例を再度構築する場合、このバージョンの PMD (4.2.6) ではこの警告はトリガーされません。Sonar は、PMD、Checkstyle、およびその他のツールを統合し、概要を提供するだけです。そのため、使用している Sonar (および PMD) のバージョンを確認してください。

ソナーでそれを見ることができます:Sonar > Quality Profiles > Search for "overr"使用しているルールを強調表示する必要があります。

Sonar では、使用している PMD のバージョンを確認できます。に移動しSonar > Configuration > Update Center、使用している PMD のバージョンを確認します。

于 2013-07-24T11:43:49.607 に答える