如何知道哪个变量是try块的罪魁祸首?

guo*_*guo 40 java exception-handling exception

在某个try块中,我有两个String变量可能导致NumberFormatException我用户Integer.parseInt(string1)Integer.parseInt(string2).问题是,如果我catch是一个例外,如何知道哪个字符串是麻烦制造者?我需要得到麻烦制造者的变量名称.

这是一些示例代码:

public class test {
    public static void main(String[] args) {
        try {
            String string1 = "fdsa";
            String string2 = "fbbbb";
            Integer.parseInt(string1);
            Integer.parseInt(string2);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        }
    }
Run Code Online (Sandbox Code Playgroud)

并且该方法e.printStackTrace()没有告诉我变量名称; 它只是告诉我麻烦制造者的内容.

java.lang.NumberFormatException:对于java.lang.Integer中java.lang.Integer.parseInt(Integer.java:580)的java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)中的输入字符串:"fdsa". parseInt(Integer.java:615)at the test.main(test.java:9)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect .delegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

进程以退出代码0结束

我需要知道变量名称的原因是我需要提示用户发生了什么.例如,通过使用告诉用户string1是错误的

System.out.println(troubleMakerName + "is wrong!")
Run Code Online (Sandbox Code Playgroud)

在我的要求中,用户应该输入

fd=(fileName,maxLength,minLength)
Run Code Online (Sandbox Code Playgroud)

然后我将分析输入字符串并创建一些响应.所以,我想检查是否maxLengthminLength将抛出NumberFormatException.在这种情况下,如果minLength有问题,那么我需要提示用户minLength是错误的.

Pol*_*ome 68

你有一个XY问题.

您不想读取实际的变量名称.您希望能够验证输入并向用户提供合理的错误消息.

String fileName, maxLengthInput, minLengthInput;
int maxLength, minLength;

List<String> errors = new ArrayList<>();

try {
    maxLength = Integer.parseInt(maxlengthInput);
} catch (NumberFormatException nfe) {
    errors.add("Invalid input for maximum length, input is not a number");
}

try {
    minLength = Integer.parseInt(minlengthInput);
} catch (NumberFormatException nfe) {
    errors.add("Invalid input for minimum length, input is not a number");
}

// show all error strings to the user
Run Code Online (Sandbox Code Playgroud)

不直接抛出异常但收集异常允许您一次通知用户所有无效输入(可能用红色突出显示相关字段),而不是让他们修复一个输入,尝试再次提交,然后查看另一个输入也是错的.

您可以使用包含相关字段等信息的自己的数据结构代替字符串,但这很快就会超出范围.主要要点是:使用两个try-catch块,您可以区分哪个字段是错误的.

如果涉及更多输入,您可以将其重构为循环.

  • 想象你有10个这样的变量需要检查,在这种情况下你会添加10个`try-catch`块吗?它看起来像代码重复 (9认同)
  • @AndrewTobilko No.通常你会从UI获得这些输入.这意味着你已经掌握了一些可以将其全部插入的数据结构.因此,我只会遍历我需要的字段,应用必要的验证器(将被抽象掉)并收集有关未通过验证的所有字段的信息并向用户显示正确的信息.但我不会仅为两个字段和两个值设计这样的架构.简单有时候是最好的.但如果你正确地阅读了我的答案,我明确表示我会使用更多字段的循环. (8认同)
  • "对于那些使用番石榴的人" (3认同)
  • @AndrewTobilko - 这就是为什么我们也有通用编程. (2认同)

Cha*_*ara 10

使用2个独立的try,catch块解析两个输入为每个变量.然后在每个catch块内生成健全性检查消息.

        String string1 = "fdsa";
        String string2 = "fbbbb";
        try {
            Integer.parseInt(string1);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            **//Please provide a valid integer for string1**
        }
        try {
            Integer.parseInt(string2 );
        } catch (NumberFormatException e) {
            e.printStackTrace();
           **//Please provide a valid integer for string2** 
        }
Run Code Online (Sandbox Code Playgroud)


And*_*lko 6

我想写自己的parseInt方法:

public static int parseInt(String s, 
                           Supplier<? extends RuntimeException> supplier) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        throw (RuntimeException)supplier.get().initCause(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

据我所知,我们无法通过反射读取变量名,所以我只是传递一个String文字:

parseInt(string1, () -> new NumberFormatException("string1"));
Run Code Online (Sandbox Code Playgroud)

我将留下原始答案,并提供在评论中讨论过的版本.但就目前而言,我很困惑为什么供应商是一种过度杀伤力.

public static int parseInt(String s, String message) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        throw (NumberFormatException)new NumberFormatException(message).initCause(e);
        // throw new IllegalArgumentException(message, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

它的电话看起来像

parseInt(string1, "string1");
Run Code Online (Sandbox Code Playgroud)

  • Java8供应商过度,你可以使用`parseInt(String maybeNumber,String variableName)`然后`抛出新的IllegalArgumentException(variableName +"不是数字!",e);`.这也使堆栈跟踪更清洁. (7认同)