web-dev-qa-db-ja.com

javaの内部クラス内の変数へのアクセス

JLabelの配列を作成しようとしています。クリックすると、すべてが非表示になります。問題は、ラベルの宣言に使用されるループの反復変数にアクセスする必要がある内部クラスを介してマウスリスナーを設定しようとするときに発生します。コードは自明です:

    for(int i=1; i<label.length; i++) {
       label[i] = new JLabel("label " + i);
       label[i].addMouseListener(new MouseAdapter() {
          public void mouseClicked(MouseEvent me) {
             label[i].setVisible(false);   // compilation error here
          }
       });
       cpane.add(label[i]);
    }

内部メソッド内でlabel[i]を呼び出す代わりにthisまたは多分superを使用することでこれを克服できると思いましたが、それを理解することができませんでした。

コンパイルエラーは次のとおりです。ローカル変数iは内部クラス内からアクセスされます。最終的に宣言する必要があります `

その答えは私が考えたことのない本当にばかげたものであるに違いないと確信しています。

どんな助けもいただければ幸いです

17
Oscar Wahltinez

内部(および匿名)クラスからアクセスするには、ローカル変数がfinalである必要があります。

次のようなコードを変更できます。

for (int i = 1; i < label.length; i++) {
    final JLabel currentLabel =new JLabel("label " + i); 
    currentLabel.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent me) {
            currentLabel.setVisible(false);   // No more compilation error here
        }
    });
    label[i] = currentLabel;
}

JLSから:

使用されているが内部クラスで宣言されていないローカル変数、仮パラメーター、または例外パラメーターは、finalとして宣言する必要があります。

内部クラスで使用されているが宣言されていないローカル変数は、必ず内部クラスの本体の前に (§16) を割り当てる必要があります。


リソース:

27
Colin Hebert

iへのアクセスに問題がある場合は、内部クラスのスコープ外に別の変数を作成します(例:label[i].addMouseListener(...)の前):

for(int i=1; i<label.length; i++) {
   label[i] = new JLabel("label " + i);

   final int localI = i;
   label[i].addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
         label[localI].setVisible(false);
      }
   });
   cpane.add(label[i]);
}
4
user153498

プログラムでgetSourceを使用することもできます。この後、typecastingを使用してコンポーネントにアクセスできます。それは余分なコード行を減らします、あなたのコードはこのようになります

for (int i = 1; i < label.length; i++) { 
   currentLabel.addMouseListener(new MouseAdapter(e) {
      public void mouseClicked(MouseEvent me) {
         JLabel label = (JLabel) me.getSource();
      }
   });
}
2
Devesh Jadon

これは、labelfinalとして指定されていないために発生します。

ラベルの配列を次のように宣言します。

final JLabel[] label;

の代わりに:

JLabel[] label;

MouseAdapterは内部クラスではありません。 anonymousクラスです。匿名クラスは、それらを囲むコードのfinal変数のみを参照できます。

0
Isaac

匿名の内部クラスは、finalである囲んでいるメソッドの変数にのみアクセスできます。

0
meriton