Java 中的异常处理:如何拒绝 int?

Handling exceptions in Java: How to reject int?

我在处理异常时遇到问题。老实说,自学以来,我真的不明白它是如何工作的。

我正在使用一个程序,其中有一个包含以下选项的主菜单。

  1. Odd/Even - 要求用户输入一个整数并确定它是奇数还是偶数。如果用户继续输入字符,程序将不断要求输入整数。 (我能够做到这一点,但是当我使用 br.readLine() 获取输入时,我一直在出错。请看下面的代码。所以我使用了正常的解析。因为我没有使用 Buffered Reader, 我尝试删除它,但 Odd/Even 程序没有它就无法处理异常。)

  2. Vowel/Consonant - 要求用户输入字符并确定它是元音字母还是辅音字母。程序应该拒绝整数输入。我用下面的代码制作的程序不拒绝整数输入。我尝试搜索答案,但找不到答案。

      1. 请暂时忽略。

我的problem/sinvolve/s下面的问题。 1. 为什么当我尝试删除 BufferedReader 行时程序 Odd/Even 不处理 NumberFormat 异常,即使它没有在整个程序中使用?

  1. 如何拒绝 Vowel/Consonant 程序的整数输入?

这是我尝试 运行 该程序时的视频。

http://tinypic.com/r/24ou9kz/9

当我退出程序时,控制台显示这个。

Exception in thread "main" java.lang.NumberFormatException: null at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.parseInt(Unknown Source)

import javax.swing.JOptionPane;

import java.io.*;

import java.util.InputMismatchException;

public class DoWhileIf {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input;
        int choice, num = 0;
        char again = 0;
        boolean err = true;
        do {
            input = JOptionPane.showInputDialog("Menu\n[1] Odd/Even\n[2] Vowel/Consonant\n[3] CQM\n[4] Fuel Efficiency\n[5] Scholarship\n[6] Exit program.\n\nEnter Choice.");
            choice = Integer.parseInt(input);

            if (choice == 1) {

                do {
                    do {
                        try {
                            input = JOptionPane.showInputDialog("Input an integer : ");
                            num = Integer.parseInt(input);
                            err = false;
                        } catch (NumberFormatException o) {
                            JOptionPane.showMessageDialog(null,"Error!");
                            err = true;
                        } 
                    } while (err);

                        if (num % 2 == 0) {
                            JOptionPane.showMessageDialog(null,"Even.");
                        }

                        else {
                            JOptionPane.showMessageDialog(null,"Odd.");
                        }
                        do {
                            input = JOptionPane.showInputDialog("Try again? Press Y for yes or N to go back to main menu.");
                            again = input.charAt(0);
                        } while (again != 'Y' && again != 'y' && again !='N' && again !='n');
                    } while (again == 'Y' || again == 'y');             
                }

            if (choice == 2) {
                char letter = 0;
                do {
                    do {
                        try {
                            input = JOptionPane.showInputDialog("Character : ");
                            letter = input.charAt(0);
                            err = false;
                        } catch (InputMismatchException a) {
                            JOptionPane.showMessageDialog(null,"Error!");
                            err = true;
                        }
                    } while (err); 

                    if (letter == 'a' || letter == 'A' || letter == 'e' || letter == 'E' || letter == 'i' || letter == 'I' || letter == 'o' || letter == 'O' || letter == 'u' || letter == 'U') {
                        JOptionPane.showMessageDialog(null,"Vowel");
                    }
                    else {
                        JOptionPane.showMessageDialog(null,"Consonant");
                    }
                    do {
                        input = JOptionPane.showInputDialog("Try again? Press Y for yes or N to go back to main menu.");
                        again = input.charAt(0);
                    } while (again != 'Y' && again != 'y' && again !='N' && again !='n');
                } while (again == 'Y' || again == 'y');
            }
        } while (choice <= 0 || choice > 6 || again == 'N' || again == 'n');
    }
  1. Why doesn't the program Odd/Even handle the NumberFormat exception whenever I try to delete the BufferedReader line even though it wasn't used in the whole program?

我无法重现这个问题。我删除了 BufferedReader 并且选项 #1 与以前一样工作。我输入了整数值、特殊字符、字母、空格,一切正常。

  1. How can I reject integer inputs for the Vowel/Consonant program?

您可以修改您的 else 条件:

else {
    JOptionPane.showMessageDialog(null,"Consonant");
}

对此:

else if(Character.isLetter(letter)){
    JOptionPane.showMessageDialog(null,"Consonant");
}
else{
    JOptionPane.showMessageDialog(null,"Error! You must enter a valid letter.");
}

When I exit the program, the console shows this. Exception in thread "main" java.lang.NumberFormatException: null at ...

关于您所看到的 NumberFormatException,我猜您是按了对话框中的“取消”按钮。当您按下取消时,变量 input 接收到值 null。当您尝试将 null 解析为整数时,它会失败并抛出异常:

Exception in thread "main" java.lang.NumberFormatException: null
    at java.lang.Integer.parseInt(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at exception.DoWhileIf.main(DoWhileIf.java:18)

第 18 行是这一行:choice = Integer.parseInt(input);

注意异常是如何告诉我们的 - java.lang.NumberFormatException: null 告诉我们传递给 parseInt 方法的参数是空的。

最后一些额外的想法供您考虑:

无论何时你从用户那里得到输入,你都必须以某种方式考虑所有的可能性。例如,当您有这样的代码时:

letter = input.charAt(0);

您没有考虑输入可能为 null 或空的可能性,在这种情况下此逻辑将抛出异常。

一个具体的例子是,当用户在询问他们是否要重试的对话框中单击“取消”时:

input = JOptionPane.showInputDialog("Try again? Press Y for yes or N to go back to main menu.");

当用户在此对话框中单击“取消”时,会发生与我在上面描述的关于 NumberFormatException 相同的事情 - 输入变为空。如果您尝试使用这样的输入:

again = input.charAt(0);

它将失败,但例外情况是:

Exception in thread "main" java.lang.NullPointerException

因为您不能在 null 上调用方法。

另一个例子是当用户在主菜单中没有输入任何内容而只是简单地按下 OK 时。结果是这个异常:

Exception in thread "main" java.lang.NumberFormatException: For input string: ""

发生这种情况是因为 input 被设置为空字符串,而 parseInt 不知道如何将空字符串转换为整数值。

我想提出的另一点是您一遍又一遍地使用同一段代码。每当您有要重用的代码时,您不应该复制和粘贴它,而应该创建一个方法、对象或其他构造以便您可以引用它。

do {
    input = JOptionPane.showInputDialog("Try again? Press Y for yes or N to go back to main menu.");
    again = input.charAt(0);
} while (again != 'Y' && again != 'y' && again !='N' && again !='n');

将您的逻辑分解成更小、更易于管理的部分将帮助您更轻松地调试、测试和维护您的代码。

关于同一逻辑块,我想谈一谈的另一点是,您正在使用相同类型的对话框来请求许多不同类型的输入。由于您使用的是 GUI 对话框,因此您可以使用更适合您的任务的对话框,例如要求用户按下 Yes 按钮或 No 按钮的对话框。

您可以通过阅读 How to Make Dialogs Tutorial

了解有关不同类型对话框的更多信息

以下是如何创建更友好对话的示例:

/**
 * Asks the user if they want to try something again and
 * returns a boolean representing the user's response.
 * @return true if the user answers Yes, false otherwise.
 */
private static boolean promptToRepeatSelectedOption(){
    int n = JOptionPane.showOptionDialog(null,
            "Try again?",
            "Repeat Selection",
            JOptionPane.YES_NO_OPTION,
            JOptionPane.QUESTION_MESSAGE,
            null,
            null,
            null);
    return n == JOptionPane.YES_OPTION;
}

调用上述方法时,将创建并显示一个带有两个按钮的对话框 - 是和否 - 用户必须 select 其中一个按钮或关闭对话框。如果用户说“是”(通过单击“是”按钮)并且 returns 为真,则该逻辑会简单地查找。如果用户关闭对话框或选择否选项,则方法 returns 为 false,因为这两种情况中的任何一种都会导致 n == JOptionPane.YES_OPTION 比较结果为 false.

您可以像这样调用此方法来替换整个循环:

首先,定义一个变量来保存用户的响应。 boolean repeat = false;

然后调用该方法并将变量设置为其结果: repeat = promptToRepeatSelectedOption();

现在替换外循环条件 while (again == 'Y' || again == 'y');

用这个:while (repeat);

最后替换部分最外层的循环条件 again == 'N' || again == 'n'

用这个:!repeat

最后一个想法是,当用户输入不正确或无效的内容时,您使用的是非常普遍的错误消息: JOptionPane.showMessageDialog(null, "Error!");

最好向用户稍微解释一下他们做错了什么,以便他们知道下次如何避免错误。您可能应该考虑在错误消息中添加更多详细信息。

希望对您有所帮助!