简体   繁体   English

无法引用封闭 scope 中定义的非最终局部变量显示

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

This might be a very basic question.这可能是一个非常基本的问题。 But I am stuck at this.但我坚持这一点。 The error that I get for the String variable display states:我得到的字符串变量display错误状态:

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

If I use a final keyword, I get the message:如果我使用final关键字,我会收到以下消息:

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

The code is:代码是:

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

Thanks in advance!提前致谢!

There are multiple issues with your code, and we'll address them right here, right now and solve your problem at the same time.您的代码存在多个问题,我们将在此处立即解决这些问题并同时解决您的问题。

  1. public class Frame { this particular line has an error, Frame is the name of an AWT class, so it might confuse you or anyone who reads this code later on, give it a more meaningful name and avoid those names that could be confused with other Java packages. public class Frame {此特定行有错误, Frame是 AWT class 的名称,因此它可能会使您或稍后阅读此代码的任何人感到困惑,给它一个更有意义的名称并避免那些可能与其他名称混淆的名称Java 封装。

  2. Frame ob=new Frame(); you create an instance of your class and never use it again, why?你创建了一个 class 的实例,然后再也不用它了,为什么?

  3. frame.setLayout(null); NEVER , please don't use null-layout , Swing has to deal with multiple PLAFs, screen sizes and resolutions, different OS, pixel perfect apps might seem like the easiest way to create complex UIs but later on you'll find that errors like this happen very often.绝不,请不要使用null-layout ,Swing 必须处理多个 PLAF、屏幕尺寸和分辨率、不同的操作系统、像素完美的应用程序似乎是创建复杂 UI 的最简单方法,但稍后您会发现类似的错误这种情况经常发生。

  4. .setBounds(...) on every component, again, this is due to null-layout but it's better to use Layout managers .setBounds(...)在每个组件上,同样,这是由于null-layout ,但最好使用布局管理器

  5. final JTextField name=new JTextField(); There's no need to declare any of your components as final , this is due to a poor design of your class, your components should be declared as class members (outside any method including main ).无需将您的任何组件声明为final ,这是由于 class 的设计不佳,您的组件应声明为 class 成员(在包括main在内的任何方法之外)。

  6. Speaking about main , separate your program into smaller pieces, don't throw everything at main or at the very least create a method that is not static so you can call it after creating an instance of your class (or else later on you'll end up with tons of static variables and that's a poor design of your class once again).说到main ,将您的程序分成更小的部分,不要将所有内容都扔到main或至少创建一个不是static的方法,这样您就可以在创建 class 的实例后调用它(否则稍后您将最终得到大量的static变量,这又是 class 的糟糕设计)。

  7. System.exit(0); it will stop the JVM, it's never a good idea to do that, it's better to .dispose() the JFrame and have your JFrame 's defaultCloseOperation set to EXIT_ON_CLOSE which will safely dispose your app and then stop the JVM. it will stop the JVM, it's never a good idea to do that, it's better to .dispose() the JFrame and have your JFrame 's defaultCloseOperation set to EXIT_ON_CLOSE which will safely dispose your app and then stop the JVM.

  8. display=name.getText(); , for this particular case, display could be an inner variable rather than a class member. ,对于这种特殊情况, display可能是内部变量而不是 class 成员。 This will solve your particular question这将解决您的特定问题

  9. JOptionPane.showMessageDialog(null, "Hi "+ display); that null should be a reference to your JFrame , this will place your dialog in the middle of that JFrame rather than in the middle of the screen.null应该是对您的JFrame的引用,这会将您的对话框放在JFrame的中间而不是屏幕的中间。

  10. You never place your program inside the EDT, see point #2 in this answer .您永远不会将程序放在 EDT 中,请参阅此答案中的第 2 点。

So, having all the above points in mind, here's an improved version of your code.因此,考虑到上述所有要点,这是您的代码的改进版本。

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

And this is how it looks like now.这就是现在的样子。

在此处输入图像描述

The UI may not be perfectly equal to the one you have, but I'm sure you can play with the different layout managers, and nest various JPanel s to get a much better looking UI than mine, or at least a more similar one to the one you had. UI 可能并不完全等同于您拥有的 UI,但我相信您可以使用不同的布局管理器,并嵌套各种JPanel以获得比我的 UI 更好看的 UI,或者至少与你拥有的那个。

Variable used in side an inner class should be effectively final.内部 class 中使用的变量应该是有效的最终变量。 You can use a string[] of length 1 instead of string to resolve this.您可以使用长度为 1 的 string[] 而不是 string 来解决此问题。 Please read bellow post for more details请阅读下面的帖子了解更多详情

Difference between final and effectively final 最终和有效最终之间的区别

Also check this post for more details另请查看此帖子以获取更多详细信息

Variable used in lambda expression should be final or effectively final lambda 表达式中使用的变量应该是最终的或有效的最终的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法引用封闭范围中定义的非最终局部变量jSONString - Cannot refer to the non-final local variable jSONString defined in an enclosing scope 无法引用封闭范围中定义的非最终局部变量按钮,随机方法错误 - Cannot refer to the non-final local variable button defined in an enclosing scope, Random method error “不能引用封闭 scope 中定义的非最终局部变量。” 更改执行环境后 - “Cannot refer to the non-final local variable defined in an enclosing scope.” after changing Execution Environment 将字符串保存在Login类的sharedpreferences中以在MainActivity中使用-无法引用定义的非最终局部变量编辑器 - Saving a string in sharedpreferences in Login class to be used in MainActivity - Cannot refer to the non-final local variable editor defined Volley:无法在android中引用非最终局部变量 - Volley:Cannot refer to the non-final local variable in android Java-无法引用非最终变量 - Java - Cannot refer to a non-final variable 无法引用非最终变量 - Cannot refer to a non-final variable java不能引用非final变量 - java cannot refer to non-final variable 无法引用非最终变量和计时器 - Cannot refer to non-final variable and Timer 为什么非最终的“局部”变量不能在内部类中使用,而是封闭类的非最终字段可以? - Why a non-final “local” variable cannot be used inside an inner class, and instead a non-final field of the enclosing class can?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM