2016-04-17 4 views
2

HandlerThreadで以下のクラスを使用して更新ストリームを作成しようとしていますが、Javaで変数キャプチャがどのように機能するかについていくつか質問があります。Runnableで囲みスコープをキャプチャする方法

[1]retは参考として取り上げていますか?

[2]thisRunnableを参照していますか、それとも囲いの範囲から取り込まれていますか?

[ボーナス]StartStreamはハンドラスレッドにRunnableを投稿し、そして唯一のRunnableが完了したときに返す必要があります。下のコードは期待どおりに動作しますか?

public class Stream extends HandlerThread { 
    Handler handler = null; 

    Stream() { 
     super("Stream"); 
     handler = new Handler(getLooper()); 
     start(); 
    } 

    private int _startStream() { // Start some repeating update 
     return 1; 
    } 

    public int StartStream() { 
     int ret = -1; 

     handler.post(new Runnable(){ 
      @Override public void run() { 
       synchronized(this) { 
        ret = _startStream(); // [1] 
        this.notify();   // [2] 
       } 
      } 
     }); 

     synchronized(this) { 
      while(ret == -1) { 
       try { 
        this.wait(); 
       } 
       catch (InterruptedException e){} 
      } 
     } 

     return ret; 
    } 
} 
+2

なぜあなたは 'HandlerThread'を拡張していますか? – pskink

+0

@pskinkなぜですか? – bitwise

+0

'HandlerThread'は直接使用するように設計されているため、 – pskink

答えて

3

内部クラスには外部クラスへの暗黙の参照があります。

retを匿名の内部クラスで使用するには、それは最終的なものでなければなりません。ローカル変数が非finalとして参照できないのは、メソッドが返ってからローカルクラスインスタンスがメモリ内に残るためです。また、java versionに依存します。それでも、「効果的に最終的に」、またはメンバー変数に移動する必要があります。

thisはRunnableを指します。Stream.thisを使用してください。

+0

私はあなたに「ret」の意味を理解していません。 Runnableの囲みスコープに変数/フラグを設定する必要があります。どのようにして 'ret'の最終/読み取り専用を達成するのですか? – bitwise

+0

ローカル変数は、範囲外になる可能性があるため、セーフティメカニズムとして自動的に最終的にキャプチャされますか? – bitwise

+0

コンパイラを満たすためにfinalを追加する必要があります –

1

retはローカル変数であり、したがって効果的に最終的になる必要があります。これは、retが初期化された後に別の値に割り当てられていると、コンパイラが不平を言うことを意味します。したがって[1]はコンパイラエラーを引き起こします。

これは、Java言語アーキテクトが、ローカル変数(メソッドで宣言されている変数)を宣言するメソッド以外の場所から変更しないようにするためです。封入法から変数捕捉の詳細について

this

実際Runnableインスタンスを参照しません。ただし、Stream.thisを使用して、同封のStreamインスタンスを参照することができます。

関連する問題