简体   繁体   中英

Cannot refer to a non-final variable lblNewLabel inside an inner class defined in a different method

I am using eclipse and windows builder --> Swing --> Jframe . I have added textField , lblNewLabel and btnNewButton . By clicking and dropping it on contentPane . When trying to assign a value to a lblNewLabel using methods lblNewLabel.setText(textField.getText()); . I get the following error: Cannot refer to a non-final variable lblNewLabel inside an inner class defined in a different method .

This is my source code:

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

}

Why is this happening? I was reading some answers that say: "Java requires references to variables from inner classes to be final variables" but if needed why doesn't Jframe insert it as such automatically. My textField is working and I can get and set Its value using the same methods. I was meaning to ask why and how to solve this. I appreciate your help.

You most probably want to change the settings of the window builder with this option "Declare variable as final" on local varaibles.

在此处输入图片说明

This should do the trick, since "... . However, a local class can only access local variables that are declared final."

Alternative with fields

Consider using the "convert to local field" operation inside the window builder.

在此处输入图片说明

This will change the definition of the label from

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

into

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

Environment

Everything tested using

  • eclipse Version: Kepler Service Release 1 | Build id: 20130919-0819
  • window builder Version: 1.6.1 | Build 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 version

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)

My question is why do i have to tweak the code to use a simple example of assigning a value to a label. Given that i don't need to do that for a text field

lblNewLabel is a local variable that can't be accessed inside the anonymous inner class until and unless it's final.

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

where as textField is instance member that can be accessed easily inside the anonymous inner class.

private JTextField textField;

Inner class and local variables

Local variables always live on the stack, the moment method is over all local variables are gone.

But your inner class objects might be on heap even after the method is over (Say an instance variable holds on to the reference), so in that case it cannot access your local variables since they are gone, unless you mark them as final .

The local variable could change before the inner class accesses it. Making it final prevents that because final variable can't be changed once assigned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM