无法引用封闭范围内定义的非最终局部变量显示

Cannot refer to the non-final local variable display defined in an enclosing scope

这可能是一个非常基本的问题。但我坚持这一点。我得到的字符串变量 display 的错误是:

Cannot refer to the non-final local variable display defined in an enclosing scope.

如果我使用 final 关键字,我会收到消息:

The final local variable display cannot be assigned, since it is defined in an enclosing slope.*

密码是:

public class Frame {

public static void main(String[] args) {
    String display=" ";
    Frame ob=new Frame();
    JFrame frame=new JFrame("Test");
    frame.setBounds(300,100,800,500);
    //Container c=frame.getContentPane(); 
    frame.setLayout(null);
    final JTextField name=new JTextField();
    name.setBounds(500,212,150,20);
    JLabel nameLabel=new JLabel("Name: ");
    nameLabel.setForeground(Color.WHITE);
    nameLabel.setBounds(450,171,100,100);
    JTextField ohr=new JTextField();
    ohr.setBounds(500,282,150,20);
    JLabel ohrID=new JLabel("OHR ID: ");
    ohrID.setForeground(Color.WHITE);
    ohrID.setBounds(450,241,100,100);

    final JButton button=new JButton("Submit");
    button.setBounds(530,350,90,20);
    frame.add(name);
    frame.add(ohr);
    frame.add(ohrID);
    frame.add(nameLabel);
    frame.add(button);
    frame.getContentPane().setBackground(Color.DARK_GRAY);
    frame.setVisible(true);

    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            if(e.getSource()==button){
                display=name.getText();
                JOptionPane.showMessageDialog(null, "Hi "+ display);
                System.exit(0);
            }
        }
    });
}

提前致谢!

内部 class 中使用的变量应该是有效的 final 。您可以使用长度为 1 的字符串 [] 而不是字符串来解决此问题。请阅读下文post了解更多详情

Difference between final and effectively final

另请查看此 post 了解更多详情

您的代码存在多个问题,我们将立即在此处解决这些问题,同时解决您的问题。

  1. public class Frame { 这一行有错误,Frame 是 AWT 的名称 class,所以它可能会让您或任何阅读此代码的人感到困惑稍后,给它一个更有意义的名字,避免那些可能与其他 Java 包混淆的名字。

  2. Frame ob=new Frame(); 你创建了你的 class 的一个实例并且再也没有使用它,为什么?

  3. frame.setLayout(null); NEVER,请不要使用 null-layout,Swing 必须处理多个 PLAF、屏幕尺寸和分辨率,不同的 OS,像素完美的应用程序似乎是创建复杂 UI 的最简单方法,但稍后您会发现错误 经常发生。

  4. .setBounds(...) 在每个组件上,同样,这是由于 null-layout 但最好使用 Layout managers

  5. final JTextField name=new JTextField(); 没有必要将您的任何组件声明为 final,这是因为您的 class 设计不佳,您的组件应该是声明为 class 成员(在任何方法之外,包括 main)。

  6. 说到 main,将你的程序分成更小的部分,不要把所有东西都放在 main 或者至少创建一个不是 [=23 的方法=] 所以你可以在创建你的 class 实例后调用它(否则稍后你会得到大量的 static 变量,这是你的 class once 的糟糕设计再次)。

  7. System.exit(0); 它将停止 JVM,这样做绝不是一个好主意,最好 .dispose() JFrame 并让您的 JFramedefaultCloseOperation 设置为 EXIT_ON_CLOSE,这将安全地处理您的应用程序,然后停止 JVM。

  8. display=name.getText();,对于这种特殊情况,display 可能是内部变量而不是 class 成员。 这将解决您的特定问题

  9. JOptionPane.showMessageDialog(null, "Hi "+ display); null 应该是对你的 JFrame 的引用,这会将你的对话框放在那个 JFrame 的中间,而不是在屏幕中间。

  10. 您永远不会将程序放在 EDT 中,请参阅 中的第 2 点。

因此,考虑到以上所有要点,这是您的代码的改进版本。

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class UsingVariablesInsideActionListenerExample {
    //We declare our components here
    private JFrame frame;
    private JButton button;
    private JTextField name;
    private JTextField ohr;
    private JLabel nameLabel;
    private JLabel ohrID;
    private JPanel pane;
    private JPanel namePane;
    private JPanel ohrPane;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new UsingVariablesInsideActionListenerExample()::createAndShowGUI); //This is using Java 8 lambdas to place your program in the EDT
    }

    private void createAndShowGUI() {
        frame = new JFrame("Test"); //Create your JFrame 
        
        pane = new JPanel();
        pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS)); //This will make this JPanel to arrange components vertically
        
        namePane = new JPanel(); //By default, JPanels have FlowLayout which will arrange components horizontally
        ohrPane = new JPanel();
        
        name = new JTextField(10); //We create a JTextField with 10 columns 
        nameLabel = new JLabel("Name: ");
        nameLabel.setForeground(Color.WHITE);
        
        ohr = new JTextField(10);
        ohrID = new JLabel("OHR ID: ");
        ohrID.setForeground(Color.WHITE);

        button = new JButton("Submit");
        
        //Add the action listener
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == button) {
                    String display = name.getText(); //The display variable is now an inner variable rather than a class member
                    JOptionPane.showMessageDialog(frame, "Hi " + display);
                    frame.dispose(); //We dispose the JFrame and it will be closed after due to EXIT_ON_CLOSE below.
                }
            }
        });
        
        //We add the components to the namePane (horizontally), the order matters
        namePane.add(nameLabel);
        namePane.add(name);
        
        //Now we add these components to the ohrPane (horizontally again)
        ohrPane.add(ohrID);
        ohrPane.add(ohr);
        
        //We then add the name and ohr panes to a bigger JPanel (pane, which if you remember will add them vertically) and we add the button at the end
        pane.add(namePane);
        pane.add(ohrPane);
        pane.add(button);
        
        //We make them non opaque (transparent) so that we can see the background color of the JFrame
        namePane.setOpaque(false);
        ohrPane.setOpaque(false);
        pane.setOpaque(false);
        
        frame.add(pane);
        
        frame.getContentPane().setBackground(Color.DARK_GRAY);
        frame.pack(); //This will get every component's preferred size and make the JFrame as small as possible where it looks good on every OS, PLAF, screen size and resolution.
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true); //We make the frame visible (always at the very end, when we've added everything to it).
    }
}

这就是现在的样子。

UI 可能与您拥有的并不完全相同,但我相信您可以使用不同的布局管理器,并嵌套各种 JPanel 以获得更好的效果看起来比我的 UI,或者至少与你的那个更相似。