【问题标题】:Why is my boolean value preemptively being returned?为什么我的布尔值被抢先返回?
【发布时间】:2021-04-03 21:05:25
【问题描述】:

我正在开发一个登录验证器,并有一个检查用户名和密码有效性的类。检查后,在 LoginProxy 类中更新了一个布尔变量(isValidLoginCredentials),可以通过 get 方法获取该变量并用于其他目的。但是,get 方法返回的值始终是我在创建类时分配给 isValidLoginCredentials 的默认值。我认为问题在于我在有机会更新 isValidLoginCredentials 之前调用了 main() 中的 getter 方法,但我不明白应该进行哪些更改来阻止这种情况。这是类和主程序的相关部分。

public class LoginProxy implements ActionListener
{
    private JLabel usernameLabel;
    private JTextField usernameText;
    private JLabel passwordLabel;
    private JPasswordField passwordText;
    private JButton loginButton;
    private boolean isValidLoginCredentials = false;
    
    public void createLogin()
    {
        /*Here was code irrelevant to the problem I removed*/
  

        loginButton.addActionListener(new LoginProxy());
        
        loginButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e) 
            {
                String user = usernameText.getText();//get the username
                String pass = passwordText.getText();//get the password
                String credentials = user +":"+pass;//creates the string I compare to other valid 
                                                    //credentials
                
                ConcreteLoginValidator validator = new ConcreteLoginValidator(credentials);
        
                try 
                {
                    isValidLoginCredentials = validator.checkLogin();
                    System.out.println("The credentials are "+isValidLoginCredentials);
                } 
                catch (FileNotFoundException e1) 
                {
                    e1.printStackTrace();
                }
            
            }
        });
    }

    public void actionPerformed(ActionEvent e) 
    {
        // TODO Auto-generated method stub
        
    }

    public boolean getValidity()
    {
        return isValidLoginCredentials;
    }
    

这里是主要方法

public static void main(String[] args) 
    {
        boolean isValidLogin = false;
        LoginProxy proxy = new LoginProxy();
        proxy.createLogin();
        isValidLogin = proxy.getValidity();
    
        if(isValidLogin == true)
        {
            JFrame frame = MainUI.getInstance();
            frame.setSize(900, 600);
            frame.pack();
            frame.setVisible(true);
        }    
    }

我应该添加什么以便 isValidLogin=proxy.getValidity();只有在我已经输入并检查登录凭据是否正确后才返回一个值?

【问题讨论】:

  • 你不希望你的主线程阻塞;操作系统会认为它已被锁定并考虑将其杀死。如果您想在事件之后发生某些事情,请使用事件侦听器,就像您在上面的 sn-p 中使用 addActionListener 所做的那样。
  • actionPerformed() 方法是您要检查登录是否有效并基于此采取任何操作的地方。然而,当前的实现似乎相当繁琐,因为您的 LoginProxy 创建了另一个 LoginProxy 实例以在某个按钮上注册它——无论出于何种原因。

标签: java execution program-flow


【解决方案1】:

直奔主题,快速解决方法是将代码放在下面:

if(isValidLoginCredentials) {
    JFrame frame = MainUI.getInstance();
    frame.setSize(900, 600);
    frame.pack();
    frame.setVisible(true);
}

在这部分之后:

System.out.println("The credentials are "+isValidLoginCredentials);

您在 createLogin() 上调用的代码只是将操作侦听器设置为 UI 中的按钮,因此代码将在您单击按钮时执行。 最重要的是,当您打开一个窗口时,它会启动一个单独的线程。我不知道其余的代码,但假设当您实例化 LoginProxy 时,它会打开登录窗口。但是按照你写的方式,它会立即打开窗口并检查isValidLogin(它不会等你点击按钮)。

如果你想证明这一点,你可以简单地在 proxy.createLogin() 之前和之后放置一个 System.out.println。您将意识到在呈现 UI 时会到达两条线。

【讨论】:

    【解决方案2】:

    使用在关闭之前一直阻塞的模式对话框。

    非常简单的例子:

    public class Dialog {    // LoginProxy in questions code
    
        private String value = null;
        
        public void show(Window owner) {
            var dialog = new JDialog(owner, JDialog.DEFAULT_MODALITY_TYPE);
            var field = new JTextField(40);
    
            var okButton = new JButton("OK");
            okButton.addActionListener(ev -> {
                value = field.getText();
                dialog.dispose();
            });
    
            var panel = new JPanel();
            panel.add(field);
            panel.add(okButton);
    
            dialog.add(panel);
            dialog.pack();
            dialog.setLocationRelativeTo(owner);
            dialog.setVisible(true);  // this will be blocked until JDialog is closed
        }
        
        public String getValue() {
            return value;
        }
    }
    

    像这样称呼

        public static void main(String[] args) {
            var dialog = new Dialog();
            dialog.show(null);
            System.out.println(dialog.getValue());  // check if valid and open JFrame in questions code
        }
    

    恕我直言,此解决方案的优点:对话框类 (LoginProxy) 不需要了解主类和主 JFrame。它有一个明确的单一功能:请求用户输入。

    使用JOptionPane

    可以更轻松地创建对话框

    【讨论】:

      【解决方案3】:

      为了保证读取另一个线程中写入的值,必须将字段设为volatile

      private volatile boolean isValidLoginCredentials;
      

      您还必须等到其他人完成后才能阅读。这方面我留给读者。

      【讨论】:

      • @user15358848 以Thread.sleep(5000); 开头,然后读取值以使其正常工作。然后引入一个在登录完成时触发的回调/监听器。
      猜你喜欢
      • 2013-09-02
      • 2015-12-16
      • 2020-03-21
      • 2017-08-27
      • 2014-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-10
      相关资源
      最近更新 更多