线程“AWT-EventQueue-0”中的 Java 异常java.lang.NumberFormatException:对于输入字符串:“”

发布于 2025-01-10 13:54:24 字数 5144 浏览 4 评论 0原文

我的代码过早地抛出了预期的错误。我试图测试输入验证,但在验证发生之前抛出错误。当我尝试将代码恢复到工作完美的先前版本时,它抛出了与我现在正在处理的相同错误,然后才成为问题。

输入示例

下面的代码是第 137 行 - 明显的罪犯

int playerGuess = Integer.parseInt(playerGuessField.getText().trim());
    private void guessButtonClicked(){
        Validators validGuess = new Validators(this);
        int guessesRemaining = Integer.parseInt(guessesRemainingField.getText());
        int playerGuess = Integer.parseInt(playerGuessField.getText().trim());//error is thrown here
        
        if(validGuess.isValidGuess(playerGuessField, "guess")){
            //more code here but not necessarily relevant
        }
    }
    //basic structure of my validators
    public boolean isValidGuess(JTextComponent c, String fieldName){
        try {
            int validGuess = Integer.parseInt(c.getText());
            if(validGuess >= 1 && validGuess <= 10){
                return true;
            } else {
                showErrorDialog("Your " + fieldName + " must be between 1 & 10");
                c.requestFocusInWindow();
                return false;
            }
        } catch (NumberFormatException e) {
            showErrorDialog("Your " + fieldName + " must be between 1 & 10");
            c.requestFocusInWindow();
            return false;
        }
    }


这是一个例外,但它的荣耀却是例外。

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "asdf"
        at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
        at java.base/java.lang.Integer.parseInt(Integer.java:660)
        at java.base/java.lang.Integer.parseInt(Integer.java:778)
        at GameGUI.guessButtonClicked(GameGUI.java:137)
        at GameGUI.lambda$0(GameGUI.java:94)
        at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
        at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
        at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
        at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
        at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
        at java.desktop/java.awt.Component.processMouseEvent(Component.java:6617)
        at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
        at java.desktop/java.awt.Component.processEvent(Component.java:6382)
        at java.desktop/java.awt.Container.processEvent(Container.java:2264)
        at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4993)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2322)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4825)
        at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4934)
        at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4563)
        at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4504)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2308)
        at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2773)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4825)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

My code is throwing an expected error too early. I was trying to test input validation, but I'm throwing an error before validation occurs. When I tried restoring my code to a previous version that worked perfectly fine it throws the same error I'm dealing with now before it was a problem.

example of the input

The code below is line 137 - the apparent offender

int playerGuess = Integer.parseInt(playerGuessField.getText().trim());
    private void guessButtonClicked(){
        Validators validGuess = new Validators(this);
        int guessesRemaining = Integer.parseInt(guessesRemainingField.getText());
        int playerGuess = Integer.parseInt(playerGuessField.getText().trim());//error is thrown here
        
        if(validGuess.isValidGuess(playerGuessField, "guess")){
            //more code here but not necessarily relevant
        }
    }
    //basic structure of my validators
    public boolean isValidGuess(JTextComponent c, String fieldName){
        try {
            int validGuess = Integer.parseInt(c.getText());
            if(validGuess >= 1 && validGuess <= 10){
                return true;
            } else {
                showErrorDialog("Your " + fieldName + " must be between 1 & 10");
                c.requestFocusInWindow();
                return false;
            }
        } catch (NumberFormatException e) {
            showErrorDialog("Your " + fieldName + " must be between 1 & 10");
            c.requestFocusInWindow();
            return false;
        }
    }


Here's the exception in all it's glory.

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "asdf"
        at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
        at java.base/java.lang.Integer.parseInt(Integer.java:660)
        at java.base/java.lang.Integer.parseInt(Integer.java:778)
        at GameGUI.guessButtonClicked(GameGUI.java:137)
        at GameGUI.lambda$0(GameGUI.java:94)
        at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
        at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
        at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
        at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
        at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
        at java.desktop/java.awt.Component.processMouseEvent(Component.java:6617)
        at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
        at java.desktop/java.awt.Component.processEvent(Component.java:6382)
        at java.desktop/java.awt.Container.processEvent(Container.java:2264)
        at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4993)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2322)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4825)
        at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4934)
        at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4563)
        at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4504)
        at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2308)
        at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2773)
        at java.desktop/java.awt.Component.dispatchEvent(Component.java:4825)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
        at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
        at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
        at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

誰ツ都不明白 2025-01-17 13:54:24

底线:您需要验证您的输入。

为此,我可以想到几个选项:

选项 1:使用 Scanner 检查输入是否为数字

Scanner scanner = new Scanner(playerGuessField.getText().trim());
if (scanner.hasNextInt()) {
    int playerGuess =  scanner.nextInt();
} else {
    // handle the error
}

选项 2:将第 137 行换行到 try/catch

int playerGuess = 0;
try {
    playerGuess = Integer.parseInt(playerGuessField.getText().trim());
} catch (NumberFormatException nfe) {
    // handle the exception
}

选项 中3:在文本字段中添加输入验证器。

为此,您需要创建一个输入验证器

public class MyInputVerifier extends InputVerifier {
    @Override
    public boolean verify(JComponent input) {
        String text = ((JTextField) input).getText();
        try {
            BigDecimal value = new BigDecimal(text);
            return true; // or some other evaluation (i.e. value > 0 for positive value)
        } catch (NumberFormatException e) {
            return false;
        }
    }
}

然后,您需要将其添加到字段中

field.setInputVerifier(new MyInputVerifier());

最后,您需要触发验证。这通常在呈现表单时完成。我的示例是使用 ActionListener

btn.addActionListener(e -> {
    if (!field.getInputVerifier().verify(field)) {
        System.out.println("Not valid. Clear!");
        field.setText("");
    }
});

选项 4:使用 DocumentListener

public class InputVerifierDemo {
    private static JLabel errorMsg = new JLabel("Invalid input");
    private static JFrame frame = new JFrame();
    public static void main(String[] args) {
        JTextField field = new JTextField(10);
//      field.setInputVerifier(new MyInputVerifier());
        JButton btn = new JButton("Click Me!");
//      btn.addActionListener(e -> {
//          if (!field.getInputVerifier().verify(field)) {
//              System.out.println("Not valid. Clear!");
//              field.setText("");
//          }
//      });
        JPanel panel = new JPanel();

        errorMsg.setForeground(Color.RED);
        errorMsg.setVisible(false);
        panel.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(5, 0, 0, 5);
        c.gridx = 1;
        c.gridy = 0;
        c.anchor = GridBagConstraints.SOUTH;
        panel.add(errorMsg, c);

        c.gridx = 1;
        c.gridy = 1;
        c.anchor = GridBagConstraints.CENTER;
        panel.add(field, c);

        field.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void removeUpdate(DocumentEvent e) {
                validateInput(field);
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                validateInput(field);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
            } // Not needed for plain-text fields
        });

        frame.getContentPane().add(panel);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private static void validateInput(JTextField field) {
        String text = field.getText();
        String pattern = "\\d+";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(text);
        if (m.matches()) {
            errorMsg.setVisible(false);
        } else {
            errorMsg.setVisible(true);
        }
    }

    private static class MyInputVerifier extends InputVerifier {
        @Override
        public boolean verify(JComponent input) {
            String text = ((JTextField) input).getText();
            try {
                BigDecimal value = new BigDecimal(text);
                return true; // or some other evaluation (i.e. value > 0 for positive value)
            } catch (NumberFormatException e) {
                return false;
            }
        }
    }
}

上面的代码包含输入验证器和文档侦听器解决方案,以便您可以同时使用两者。我个人更喜欢文档监听器,因为它更具交互性。我宁愿在输入字段时验证字段,而不是在填写所有字段并执行提交表单的操作后验证字段。但是,这完全取决于个人喜好。

我将选项 #1 归功于 MadProgrammer

Bottom line: You need to validate your input.

To do this, I can think of a few options:

Option 1: Use Scanner to check if the input is numeric

Scanner scanner = new Scanner(playerGuessField.getText().trim());
if (scanner.hasNextInt()) {
    int playerGuess =  scanner.nextInt();
} else {
    // handle the error
}

Option 2: Wrap line 137 in a try/catch

int playerGuess = 0;
try {
    playerGuess = Integer.parseInt(playerGuessField.getText().trim());
} catch (NumberFormatException nfe) {
    // handle the exception
}

Option 3: Add an input verifier to the text field.

For this, you need to create an input verifier

public class MyInputVerifier extends InputVerifier {
    @Override
    public boolean verify(JComponent input) {
        String text = ((JTextField) input).getText();
        try {
            BigDecimal value = new BigDecimal(text);
            return true; // or some other evaluation (i.e. value > 0 for positive value)
        } catch (NumberFormatException e) {
            return false;
        }
    }
}

Then, you need to add it to the field

field.setInputVerifier(new MyInputVerifier());

And lastly, you need to trigger the verification. This is typically done when the form is rendered. My example is using an ActionListener.

btn.addActionListener(e -> {
    if (!field.getInputVerifier().verify(field)) {
        System.out.println("Not valid. Clear!");
        field.setText("");
    }
});

Option 4: Use DocumentListener

public class InputVerifierDemo {
    private static JLabel errorMsg = new JLabel("Invalid input");
    private static JFrame frame = new JFrame();
    public static void main(String[] args) {
        JTextField field = new JTextField(10);
//      field.setInputVerifier(new MyInputVerifier());
        JButton btn = new JButton("Click Me!");
//      btn.addActionListener(e -> {
//          if (!field.getInputVerifier().verify(field)) {
//              System.out.println("Not valid. Clear!");
//              field.setText("");
//          }
//      });
        JPanel panel = new JPanel();

        errorMsg.setForeground(Color.RED);
        errorMsg.setVisible(false);
        panel.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(5, 0, 0, 5);
        c.gridx = 1;
        c.gridy = 0;
        c.anchor = GridBagConstraints.SOUTH;
        panel.add(errorMsg, c);

        c.gridx = 1;
        c.gridy = 1;
        c.anchor = GridBagConstraints.CENTER;
        panel.add(field, c);

        field.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void removeUpdate(DocumentEvent e) {
                validateInput(field);
            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                validateInput(field);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
            } // Not needed for plain-text fields
        });

        frame.getContentPane().add(panel);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private static void validateInput(JTextField field) {
        String text = field.getText();
        String pattern = "\\d+";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(text);
        if (m.matches()) {
            errorMsg.setVisible(false);
        } else {
            errorMsg.setVisible(true);
        }
    }

    private static class MyInputVerifier extends InputVerifier {
        @Override
        public boolean verify(JComponent input) {
            String text = ((JTextField) input).getText();
            try {
                BigDecimal value = new BigDecimal(text);
                return true; // or some other evaluation (i.e. value > 0 for positive value)
            } catch (NumberFormatException e) {
                return false;
            }
        }
    }
}

The code above contain the input verifier AND the document listener solutions so that you could play with both. I personally prefer the document listener because it is more interactive. I rather validate fields as I am typing on them, rather than after the fact when all the fields are filled and an action to submit the form takes place. But, this is all a matter of personal preference.

I credit MadProgrammer for option #1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文