为什么我的布尔值会被抢先返回?
Why is my boolean value preemptively being returned?
我正在开发一个登录验证器,并且有一个 class 可以检查用户名和密码的有效性。检查后,LoginProxy class中更新了一个布尔变量(isValidLoginCredentials),可以通过get方法获取并用于其他目的。但是,get 方法返回的值始终是我在创建 class 时分配给 isValidLoginCredentials 的默认值。我认为问题是我在有机会更新 isValidLoginCredentials 之前调用了 main() 中的 getter 方法,但我不明白我应该做哪些更改来阻止它。这是 class 和主程序的相关部分。
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(); returns我已经输入并检查了登录凭据是否正确后才显示的值?
为了保证读取另一个线程中写入的值,必须使字段volatile
:
private volatile boolean isValidLoginCredentials;
您还必须等到对方完成后再阅读。这方面我留给 reader.
开门见山,快速解决方法是将代码放在下面:
if(isValidLoginCredentials) {
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
这部分之后:
System.out.println("The credentials are "+isValidLoginCredentials);
您在 createLogin() 上调用的代码只是将动作侦听器设置为 UI 中的按钮,因此代码将在您单击按钮时执行。
最重要的是,当您打开 window 时,它会启动一个单独的线程。我不知道其余代码,但假设当您实例化 LoginProxy 时,它会打开登录 window。但是你写的方式,它会打开 window 并立即检查 isValidLogin (它不会等你点击按钮)。
如果你想证明这一点,你可以简单地在 proxy.createLogin() 前后加上一个 System.out.println。您会意识到在呈现 UI 时会到达两条线。
使用阻塞直到关闭的模态对话框。
非常简单的例子:
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
}
这个解决方案的优点恕我直言:对话 class (LoginProxy
) 不需要 知道 关于主 class 和主JFrame
。它有一个明确的单一功能:要求用户输入。
使用 JOptionPane
可以更轻松地创建对话框
我正在开发一个登录验证器,并且有一个 class 可以检查用户名和密码的有效性。检查后,LoginProxy class中更新了一个布尔变量(isValidLoginCredentials),可以通过get方法获取并用于其他目的。但是,get 方法返回的值始终是我在创建 class 时分配给 isValidLoginCredentials 的默认值。我认为问题是我在有机会更新 isValidLoginCredentials 之前调用了 main() 中的 getter 方法,但我不明白我应该做哪些更改来阻止它。这是 class 和主程序的相关部分。
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(); returns我已经输入并检查了登录凭据是否正确后才显示的值?
为了保证读取另一个线程中写入的值,必须使字段volatile
:
private volatile boolean isValidLoginCredentials;
您还必须等到对方完成后再阅读。这方面我留给 reader.
开门见山,快速解决方法是将代码放在下面:
if(isValidLoginCredentials) {
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
这部分之后:
System.out.println("The credentials are "+isValidLoginCredentials);
您在 createLogin() 上调用的代码只是将动作侦听器设置为 UI 中的按钮,因此代码将在您单击按钮时执行。 最重要的是,当您打开 window 时,它会启动一个单独的线程。我不知道其余代码,但假设当您实例化 LoginProxy 时,它会打开登录 window。但是你写的方式,它会打开 window 并立即检查 isValidLogin (它不会等你点击按钮)。
如果你想证明这一点,你可以简单地在 proxy.createLogin() 前后加上一个 System.out.println。您会意识到在呈现 UI 时会到达两条线。
使用阻塞直到关闭的模态对话框。
非常简单的例子:
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
}
这个解决方案的优点恕我直言:对话 class (LoginProxy
) 不需要 知道 关于主 class 和主JFrame
。它有一个明确的单一功能:要求用户输入。
使用 JOptionPane