5

このサンプルコードを考えると:

Runnable r = new Runnable() {
  public void run() {
    System.out.print("Cat");
  }
};
Thread t = new Thread(r) {
  public void run() {
    System.out.print("Dog");
  }
};
t.start();

なぜ出力はCatではなくDogなのですか?

4

5 に答える 5

7

runinの実装は、コンストラクターで提供されているものがあれば、それをThread呼び出すだけです。Runnableそのコードをオーバーライドしているので、新しいスレッドでrunメソッドが呼び出されただけの場合、Runnableは無視されます。もちろん、ソースコードを見てそれを確認できるはずです...(私はちょうどそうしました、そして私はここにソースを投稿するつもりはありませんが、それは私が説明したことを正確に行います。)

あなたが実際に明らかにしたのはカプセル化の問題です-スレッドが何をすThread べきかを言うこれらの異なる、潜在的に矛盾する方法を持つべきではありません。基本的に、直接拡張することはほとんどありません。Threadひどく設計されているからといって、その貧弱なデザインを悪用しなければならないという意味ではありません;)

編集:これは実際には、やや回りくどい方法で文書化されています。start()次のように文書化されています:

このスレッドに実行を開始させます。Java仮想マシンは、このスレッドのrunメソッドを呼び出します。

そしてrun()、次のように文書化されています:

このスレッドが別のRunnablerunオブジェクトを使用して構築された場合、そのRunnableオブジェクトのrunメソッドが呼び出されます。それ以外の場合、このメソッドは何もせずに戻ります。

したがって、run()メソッドはのように呼び出されますが、コンストラクターで提供されたものを呼び出す唯一のメソッドであるをstart()オーバーライドしました。run()Runnable

次のようにメソッドをオーバーライドした場合は、次の点に注意してください。

Thread t = new Thread(r) {
  public void run() {
    super.run();
    System.out.print("Dog");
  }
};

その場合、出力は「CatDog」になります。

于 2012-09-05T16:27:26.073 に答える
3

Thread.runランナブルを実行しないようにオーバーライドしました。代わりに、単に「Dog」と出力します。

于 2012-09-05T16:26:12.630 に答える
0

関数run()がオーバーライドされているためです。そしてt、この関数を呼び出します。

public void run() {
System.out.print("Dog");
}

関数を呼び出すcat実行時と同じようにo/pを取得しますr.start()

 public void run() {
    System.out.print("Cat");
  }
于 2012-09-05T16:27:04.953 に答える
0

のソースコードを見てみましょうjava.lang.Thread

public void run() {
    if (target != null) {
        target.run();
    }
}

targetコンストラクターが変数を割り当てるために使用するフィールドRunnableですThread。のメソッドをオーバーライドすると、を呼び出す動作が変更されます。Thread(Runnable)rrunThreadrun

System.out.print("Dog");

電話する代わりに

if (target != null) {
    target.run();
}
于 2012-09-05T16:30:10.067 に答える
-1

これは匿名クラスであり、を再定義/オーバーライドしていますrun。あなたはあなたの中で渡されたものを使用してRunnableいますrunか?いいえ、しません。だから問題は、なぜそれが印刷されると思ったのCatですか?

 new Thread(r) {
  public void run() {
    System.out.print("Dog");
  }
};
于 2012-09-05T16:31:56.560 に答える