26

Runnableインターフェースを実装する抽象Baseクラスがあるとしましょう。

public abstract class Base implements Runnable {

  protected int param;

  public Base(final int param) {
      System.out.println("Base constructor");
      this.param = param;
      // I'm using this param here
      new Thread(this).start();
      System.out.println("Derivative thread created with param " + param);
  }

  @Override
  abstract public void run();
}

そして、ここにいくつかの派生クラスの1つがあります。

public class Derivative extends Base {

  public Derivative(final int param) {
      super(param);
  }

  @Override
  public void run() {
      System.out.println("Derivative is running with param " + param);
  }

  public static void main(String[] args) {
      Derivative thread = new Derivative(1);
  }

}

重要なのは、Baseクラスに毎回コピーするのではなく、一般的なことを実行してもらいたいということです。実際には、正常に実行されており、出力は常に同じです。

基本コンストラクターパラメーター1で作成された派生スレッド派生物はパラメーター1で実行されています

しかし、コンストラクターで抽象メソッドを呼び出すスレッドを開始することは、JAVAでは安全ですか?なぜなら、C ++とC#では、私が知る限り、ほとんどの場合安全ではないからです。ありがとうございました!

4

4 に答える 4

37

このコードは、コンストラクターから抽象メソッドやその他のオーバーライド可能なメソッドを呼び出さない理由を示しています。

abstract class Super {
    Super() {
        doSubStuff();
    }
    abstract void doSubStuff();
}

class Sub extends Super {
    String s = "Hello world";

    void doSubStuff() {
        System.out.println(s);
    }
}

public static void main(String[] args) {
    new Sub();
}

実行すると、これは印刷されnullます。これは、コンストラクターにある唯一の「安全な」メソッドがプライベートメソッドおよび/または最終メソッドであることを意味します。

一方、コードは実際にはコンストラクターから抽象メソッドを呼び出しません。代わりに、初期化されていないオブジェクトを処理のために別のスレッドに渡します。これは、開始しているスレッドに優先順位が与えられBase、初期化が完了する前に実行される可能性があるためです。

于 2013-03-10T21:07:57.770 に答える
3

run() が呼び出されたときに Derivative オブジェクトが初期化されていない可能性があるため、お勧めできません。run() が Derivative の状態に依存している場合、失敗する可能性があります。

あなたの単純なケースではうまくいきます。しかし、サブクラスには意味がありません。簡単にできます

public Base(final int param, Runnable action) {

  new Thread(action).start();
于 2013-03-10T20:59:31.500 に答える
2

コンストラクターから抽象メソッドを呼び出すのは非常に悪い習慣です。オーバーライドを防ぐために、コンストラクターから呼び出されるメソッドは常に private または final にする必要があります。

こちらの質問へのリンクを参照してください

于 2013-03-10T20:59:22.793 に答える
1

コンストラクターからの受け渡しthisは「コンストラクターからの脱出」と呼ばれthis、オブジェクトが一貫性のない状態にある可能性があるため、特に厄介で奇妙なバグにつながる可能性があります。

thisこれは、この例のように、が別のスレッドに渡される場合に特に当てはまります。スレッド内でステートメントを並べ替えるJVMの権利により、未定義の動作/状態が発生する可能性があります。

于 2013-03-10T23:18:58.563 に答える