【问题标题】:access to variable within inner class in java访问java内部类中的变量
【发布时间】:2010-10-10 18:30:21
【问题描述】:

我正在尝试创建一个 JLabels 数组,单击时它们都应该不可见。当试图通过需要访问用于声明标签的循环的迭代变量的内部类来设置鼠标侦听器时,就会出现问题。代码不言自明:

    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]);
    }

我认为我可以通过使用 thissuper 而不是在内部方法中调用 label[i] 来克服这个问题,但我无法弄清楚。

编译错误是:局部变量i是从内部类中访问的;需要声明为final`

我确信答案一定是我没有想到的非常愚蠢的事情,或者我犯了一些小错误。

任何帮助将不胜感激

【问题讨论】:

  • 错误是:local variable i is accessed from within inner class; needs to be declared final
  • @omtinez:那么也许您应该将变量声明为final,不是吗? (也可以看看this Q&A
  • @Matt Ball,使用迭代器变量 final 不是一个好主意。

标签: java variables event-handling inner-classes jlabel


【解决方案1】:

您的局部变量必须是 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)


资源:

【讨论】:

  • 能够将迭代器变量用于我认为与问题无关的其他方法会很有帮助
  • @Colin Hebert 您的“资源”链接似乎链接了第 8.1.3 节以外的其他文档
  • @trante,谢谢它指的是以前的 JLS,由 sun 主持。它现在是最新的。
  • 更新:从 Java SE 8 开始,本地类可以访问封闭块的局部变量和参数,它们是最终的或有效的最终的。见accessing members of an enclosing class
【解决方案2】:

如果您在访问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]);
}

【讨论】:

  • 可能不是最优雅的解决方案,但我认为这应该可以完成工作
【解决方案3】:

您也可以在您的程序中使用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();
      }
   });
}

【讨论】:

    【解决方案4】:

    发生这种情况是因为 label 未指定为 final

    将标签数组声明为:

    final JLabel[] label;

    代替:

    JLabel[] label;

    您的MouseAdapter 不是内部类;这是一个匿名类。匿名类只能引用其封闭代码的final 变量。

    【讨论】:

    • 其实它是一个匿名的内部类,匿名的意思是它没有明确的名字,而inner的意思是它包含在另一个类中。
    【解决方案5】:

    匿名内部类只能访问 final 的封闭方法的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多