web-dev-qa-db-ja.com

変数を新しいRunnable宣言に渡すにはどうすればよいですか?

私は以下を持っています:

Runnable done = new Runnable()
    {
        public void run()
        {
            System.out.println("Hello");
        }
    };

そして、私のAndroidアクティビティでは、次のようなものを呼び出します:

runOnUIThread(done);

それから私はそれを呼びます。しかし、私はそれが欲しい"Hello"ハードコードされていないので、渡すことができます。そうでない場合は、印刷するすべての文字列に対してこれらの宣言の1つを用意する必要があります。

(これは実際にはAndroidの質問ですが、基本的なJavaなので、答えが簡単です)

ありがとう

23
Jimmy
final String hello = whereverItsComingFrom;
Runnable done = new Runnable()
    {
        public void run()
        {
            System.out.println(hello);
        }
    };
22

Java(そして、Androidでも同じだと思います)では、Bart van Heukelomが提案したように、匿名の内部クラスを使用できます。このソリューションコードを少なくする必要があるという利点があり、外部クラスのフィールドとメソッドにアクセスできます。

ただし、2つの欠点があります。

  • 変数「hello」はfinalである必要があります。

  • 匿名クラスには、外部クラスインスタンスへの内部参照があります。これは、外部クラスがガベージコレクションの対象となる場合に保持されることを意味します。 @See:効果的Java [Joshua Bloch]、アイテム22:非静的よりも静的メンバークラスを優先する

そして、私の謙虚な意見では、このようにクラスインスタンスをパラメータ化することは悪い習慣です。

したがって、外部クラスのメソッドとフィールドにアクセスする必要がない限り、このタスク用に特定のクラスを作成して、それをstaticメンバークラスにする方がよいと思います。

class Demo {
...

  private static class MyRunnable implements Runnable {
     private final String message;

     MyRunnable(final String message) {
       this.message = message;
     }

     public void run() {
       System.out.println(message);
     }
  }

  public void startThread() {
    MyRunnable myRunnable = new MyRunnable("Hello");

    runOnUIThread(myRunnable); 
  }
...
}
48
Ralph