2017-03-01 4 views
1

内部の最終ブール対なぜ次は許可されている:最終ブール[]は、Runnableを

final boolean [] success = new boolean[1]; 
    Thread httpThread = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      HTTPConnect httpConnect = new HTTPConnect(getContext()); 
      success[0] = false 
      ... 
      if (whatever) 
      success[0] = true; 

しかし、次のではないでしょうか?

final boolean success; 
    Thread httpThread = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      HTTPConnect httpConnect = new HTTPConnect(getContext()); 
      success = false 
      ... 
      if (whatever) 
      success = true; 

ここではboolean successを参照しています。 最初は、ローカル宣言がスコープを失うためだと思っていましたが、ヒープ宣言はスコープの終了後も生き残りますが、final ArrayList<Foo> bar = new ArrayList<>()のような宣言は値を代入することができないため、そうではありません。

+1

コードから不要な部分をすべて削除すると、これが機能しない理由がわかります: 'ブールの成功; success [0] = true; ' 答えは簡単です:' success'はプリミティブなブール値で配列ではないからです。 – Kiryl

+0

@Kirylそれはタイプミスだった。 – ShrimpCrackers

答えて

1

booleanの値を実際には配列内にラップしているため、配列の内容は変更できますが、変数successの参照は変更されません。

AtomicBoolean(または一般にAtomicReference)を使用すると同じ結果が得られます。

匿名内部クラスに変更された変数の問題は、あなたがに言及されているものsuccessを変更しているので、次のシナリオ

boolean success; 
Thread httpThread = new Thread(new Runnable() { 
    @Override 
    public void run() { 
    success = false; 
    .... 

にこれが許可されていませんが生じます。 boolean[]を使用している場合は、successを参照しているのではなく、参照されているオブジェクトに含まれる値が変更されているため、問題はありません。

1

まず、2番目の例では、successbooleanなので、代入文に添字を付けないでください。

どちらの場合も、successがローカル変数であると仮定しています。それがフィールドの場合は、単にfinalを取り除くことができ、2番目のケースは(添え字を削除した後で)機能します。

ローカル変数に対して2番目の方法が機能しないのは、変数が割り当てられた後にfinal変数に割り当てることができないためです。ストーリーは配列とは少し異なります。まだ新しい配列をsuccessに割り当てることはできませんが、配列の要素に新しい値を割り当てることができます。それが最初のアプローチが機能する理由です。このような配列を使用することは、この問題とJavaメソッドに "out"引数がないという問題の両方を扱う共通の慣用表現です。