不能在不同方法中定义的内部类中引用非final变量lblNewLabel

时间:2014-06-22 11:05:33

标签: java swing final local-variables windowbuilder

我正在使用eclipsewindows builder --> Swing --> Jframe。我添加了textFieldlblNewLabelbtnNewButton。通过在contentPane上单击并将其删除。尝试使用方法lblNewLabellblNewLabel.setText(textField.getText());分配值时。 我收到以下错误:Cannot refer to a non-final variable lblNewLabel inside an inner class defined in a different method

这是我的源代码:

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


public class MultAppMed extends JFrame {

    private JPanel contentPane;
    private JTextField textField;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MultAppMed frame = new MultAppMed();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public MultAppMed() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel lblNewLabel = new JLabel("New label");
        lblNewLabel.setBounds(106, 14, 46, 14);
        contentPane.add(lblNewLabel);

        JButton btnNewButton = new JButton("New button");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                lblNewLabel.setText(textField.getText());
            }
        });
        btnNewButton.setBounds(335, 228, 89, 23);
        contentPane.add(btnNewButton);

        textField = new JTextField();
        textField.setBounds(10, 11, 86, 20);
        contentPane.add(textField);
        textField.setColumns(10);
    }

}

为什么会这样?我正在阅读一些答案:“Java需要引用内部类中的变量作为最终变量”,但如果需要,为什么Jframe不会自动插入它。我的textField正在运行,我可以使用相同的方法获取并设置其值。我的意思是问为什么以及如何解决这个问题。我感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

您可能希望使用此选项“在本地变量上声明变量为最终”来更改窗口构建器的设置。

enter image description here

这应该可以解决问题,因为"... . However, a local class can only access local variables that are declared final."

替代字段

考虑在窗口构建器中使用“转换为本地字段”操作。

enter image description here

这将改变标签的定义

JLabel lblNewLabel = new JLabel("New label");

进入

private JLabel lblNewLabel;
// in initialization method / c'tor
lblNewLabel = new JLabel("New label");

<强>环境

使用

测试的所有内容
  • eclipse 版本:Kepler Service Release 1 | Build id:20130919-0819
  • 窗口构建器版本:1.6.1 |构建ID:2013.09.10

<强>的eclipse.ini

-startup
plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.200.v20130807-1835
-product
org.eclipse.epp.package.standard.product
--launcher.defaultAction
openFile
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.6
-Xms40m
-Xmx512m

java版

C:\....\isi>java -version
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) 64-Bit Server VM (build 20.5-b03, mixed mode)

答案 1 :(得分:1)

  

我的问题是为什么我必须调整代码才能使用一个为标签赋值的简单示例。鉴于我不需要为文本字段执行此操作

lblNewLabel是一个局部变量,除非是最终的,否则无法在匿名内部类中访问。

JLabel lblNewLabel = new JLabel("New label");

其中textField是实例成员,可以在匿名内部类中轻松访问。

private JTextField textField;

Inner class and local variables

局部变量总是存在于堆栈中,当时方法已经超过所有局部变量。

但是即使方法结束后你的内部类对象也可能在堆上(假设一个实例变量保留在引用上),所以在这种情况下它不能访问你的局部变量,因为它们已经消失,除非你将它们标记为final

在内部类访问它之前,局部变量可能会发生变化。使其final可以防止这种情况,因为final变量一旦分配就无法更改。