web-dev-qa-db-ja.com

最終的なローカル変数を割り当てることはできません

座席の配列があり、配列には2つの文字列(選択済みおよび空)があります。マウスクリックで、アレイを走査して、選択した座席を見つけたいです。ボタンを押すと、次のように表示されます。

最後のローカル変数seatnoは、囲む型で定義されているため、割り当てることができません。

    JButton btnContinue = new JButton("Next");
    btnContinue.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent arg0) {

            for(int x=0;x<17;x++){
                if(anArray[x]=="selected"){

                    seatno = anArray[x];
                }
            }

            data page=new data(newfrom,newto,newtime,date2,seatno);
            page.setVisible(true);
            setVisible(false);
        }
    });
    btnContinue.setBounds(358, 227, 62, 23);
    contentPane.add(btnContinue);
36
user1326088

ポイントは、囲んでいる型のメソッドローカル変数が実際に匿名クラスのインスタンスにコピーされている(これはアクティベーションフレームの問題のためですがこれは質問に実際には関係ないため、さらに詳しくは説明しません)、ネストされた型インスタンスの変数はもはや同じではないため、最終的なものにする必要があります。

したがって、最初の例を次に示します。

_void foo() {
    int a = 3;
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}
_

匿名クラスのメソッドで非最終変数を参照できないため、これはコンパイルされません。 aの宣言にfinal修飾子を追加すると、aの値が、定義した匿名クラスの作成済みインスタンスにコピーされます。ただし、aが宣言されたメソッドには変更が表示されないため、aの値を変更することはできません。

ただし、匿名クラスは静的ではありません。つまり、クラスを囲むインスタンスへの参照があります(宣言されているメソッドが静的である場合を除く)。

_int a = 3;

void foo() {
    new Runnable() {
        @Override
        public void run() {
            a += 3;
        }
    };
}
_

この例はコンパイルを行い、匿名クラスのインスタンスのrun()メソッドが呼び出されるたびにaを3ずつ増やします。 (この例では呼び出されませんが、単なる例です。)

そのため、要約すると、変数seatnoをメソッドローカル変数から囲み型のインスタンス変数に変換する必要があります。または、まだ存在する場合は、最終変数を1回しか割り当てることができないため、最終修飾子を削除する必要があります。

更新:In Java 8、実質的に最終的な概念)変数が導入されます( Java Language Specification を参照)。しかし、この投稿の最初の例では、変数aが複数回割り当てられ、最終的に有効になりません。この例では、まだJava 8でコンパイルされません。コンパイルエラーは、「囲みスコープで定義されたローカル変数aは最終または実質的に最終でなければなりません」)

94

最終変数はその値を変更できません(C/C++のconstに似ています)。

おそらく、関数内のローカル変数ではなく、クラスのフィールド(もちろん、最終キーワードなし)にしたいでしょう。

4
gulyan

クラスメンバー変数を定義する代わりに、可変intを使用して同じことを実現することもできます。

void foo() {
    final MutableInt a = new MutableInt(3);
    new Runnable() {
        @Override
        public void run() {
           a.add(3);
        }
    };
}

MutableIntはプリミティブ型ではないため(参照により渡される)、再割り当てできるため、これは機能します。

4
Satyam Shekhar

私は最近、同様の問題に直面しました。私の場合、以下のように、最終的な配列(またはコレクション)を作成し、変数を追加する方が簡単で、匿名クラス内でこの配列に変更したかったのです。

   int a = 3;
   final int[] array = new int[1];
   array[0] = a;
   new Runnable() {
       @Override
       public void run() {
           array[0] += 3;
       }
   };
1
yurin

seatnoの宣言を知らずに、mouseClicked()メソッドに新しい変数を導入することをお勧めします。この変数はnot finalであり、変数が見えるようにseatnoと同じジョブを実行しますそのメソッド内でのみ使用されます。

ちなみに、クラス名は大文字にしてください(dataDataでなければなりません)。より明確になります。

0
Yogu

変数にfinal修飾子がないことを確認してください。

//final, can be set only when the object is created.
private final String seatno;

//no final modifier, the value can be set every time you "want"
private String seatno;

また、文字列を比較するには、equalsを使用する必要があります。

if(anArray[x].equals("selected"))
0
Luiggi Mendoza