Error: local variable imagesLabel is accessed from within inner class; needs to be declared final (Java)

Error: local variable imagesLabel is accessed from within inner class; needs to be declared final (Java)

背景

在下面的屏幕截图中,用户应该能够通过单击其中一个单选按钮来更改图像:

单击单选按钮时,图片应更改为另一张。 我已将所有图像放入一个数组中。

问题

到目前为止,当我尝试编译代码时(请参阅下面的源代码),编译器给出以下错误:

Error: local variable imagesLabel is accessed from within inner class; needs to be declared final

一旦我在相应变量前添加 final,编译时出现以下错误:

Error: <identifier> expected

Java代码(添加final后)

Icon[] images = new Icon[3];

// Get the images and store them in the images array.  These images 
// were manually resized to be similar in size prior to writing the
// program.
images[0] = new ImageIcon("/Users/grimygod/Desktop/negativeFilterExample.png");
images[1] = new ImageIcon("/Users/grimygod/Desktop/reflect.png");
images[2] = new ImageIcon("/Users/grimygod/Desktop/colorSubtraction.png");

// The images will be displayed as the image on a JLabel without text
JLabel imagesLabel = new JLabel();

// Set the initial image to be the negative filter, and add it to the panel,
// since the radio button for the negative filter is initially selected.
imagesLabel.setIcon(images[0]);
iconPanel.add(imagesLabel);
radioButtonPanel.add(iconPanel);

// Creation of "Select An Image & Apply Filter!" button
JButton selectButton = new JButton("Select An Image & Apply Filter!");
submitButtonPanel.add(selectButton);
radioButtonPanel.add(submitButtonPanel);

// Makes the whole window visible
testFrame.setVisible(true); 

// First button is selected when program is ran
button1.setSelected(true);

button1.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        final imagesLabel.setIcon(images[2]);   //  <<<<< ERROR in this line 
   }
});

您可以执行以下任一操作来解决问题:

一个。将 imagesLabel 声明为 final

final JLabel imagesLabel = new JLabel();

乙。将 imagesLabel 声明为实例变量,即在方法外部。换句话说,在 class 本身声明它。

确保从 final imagesLabel.setIcon(images[2]); 中删除 final 即它应该只是 imagesLabel.setIcon(images[2]);

问题 A

您在添加侦听器时定义了 ActionListener 类型的 anonymous inner class,请参见下面代码中的 (1)。然后你尝试访问 声明在外部(内部class)的变量imagesLabel,见下面代码中的(2)。由于此变量声明为非最终,您不能在匿名内部class[=75]中使用它 =] 像这样。

► 因此编译失败并显示消息:

Error: local variable imagesLabel is accessed from within inner class; needs to be declared final

状态 A 中的代码(添加 final 之前):

button1.addActionListener(new ActionListener() { // (1)
    @Override
    public void actionPerformed(ActionEvent e) {
        imagesLabel.setIcon(images[1]);   //  (2) <<<<< ERROR in this line 
   }
});

问题 B

尝试解决它,您按照消息的说明进行操作,并希望直接在此行中 "declare" 变量 imagesLabel 作为 final - 在下面的代码中标记为 (3) .

但是第(3)行不是变量imagesLabel的声明的位置,而不是方法调用在这个实例变量上。

编译器读取以 final 开头的源代码行,并期望此后有一个 标识符 ,但是有一个 方法调用 .

► 因此编译失败并显示消息:

Error: <identifier> expected

状态B中的代码(添加final后):

button1.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        final imagesLabel.setIcon(images[1]);   //  (3) <<<<< ERROR in this line 
   }
});

⚠ 注意: 相同的编译错误和修复(如 )适用于在同一行中用作参数的变量 images (3 ) 以上。

解决方案

您必须在声明变量 imagesLabel(以及 images 数组)的地方使用修饰符 final。然后你可以在内部 class 中访问它,就像首先在代码状态 A:

final Icon[] images = new Icon[3]; // <<< here is the other declaration

/* ... lines of code left out for clarity  ... */

// The images will be displayed as the image on a JLabel without text
final JLabel imagesLabel = new JLabel(); // <<< here is the declaration

/* ... lines of code left out for clarity  ... */

button1.addActionListener(new ActionListener() { // (1) inner class
    @Override
    public void actionPerformed(ActionEvent e) {
        imagesLabel.setIcon(images[1]);   //  (2) <<<<< now you can use the final declared variable imagesLabel
   }
});

另见

  • 问:Java: Anonymous inner class using a local variable
  • 问:Why a non-final “local” variable cannot be used inside an inner class, and instead a non-final field of the enclosing class can?
  • 问:Why are only final variables accessible in anonymous class?
  • Tutorial on Inner Classes