是否可以制作一个catch块,等待整个try块执行完毕?

时间:2018-08-16 20:39:53

标签: java parsing exception try-catch

我在做什么

我正在尝试制作一个更干净的嵌套try catch块版本,并且在解决一个非常基本的异常问题。我正在做一个可以做得很好的计算器。但是,在此之前,它必须将用户输入作为字符串并将其转换为浮点数或整数。我通过简单地调用Java的内置parseInt和parseFloat函数来做到这一点。现在,我正在使用嵌套的try catch块来做到这一点:

String stringToParse = "1.0"
try{Integer.parseInt(stringToParse);}
catch(NumberFormatException n){
    try{Float.parseFloat(stringToParse);}
    catch(NumberFormatException n){
        System.out.println(n)
        }
    }

为什么会有问题?

这对我来说很麻烦,我宁愿有一个try块来收集错误,但不会立即进入catch块,而是执行整个try并在try执行之后捕获所有错误。我自己做了一个可运行的例子,展示了我的愿望:

    String num = "1.0";
    int i = 0;
    ArrayList<Object> listofResults = new ArrayList<>();
    ArrayList<Integer> listOfErrorIndices = new ArrayList<>();
    try {
        listofResults.add(Integer.parseInt(num));
        i++;
        listofResults.add(Float.parseFloat(num));
        i++;
        listofResults.add(Integer.parseInt(num));
    } catch (NumberFormatException n) {
        listOfErrorIndices.add(i);
    }
    for (Integer element:listOfErrorIndices) {
        System.out.println(element);
        //this currently prints out 0 and I want it to print out both 0 and 
        //2 so that it catches both errors.
    }

我如何解决问题的想法/否则我曾尝试过的

我的计划是收集尝试中所有抛出的NumberFormatException索引(i)的列表。每次我尝试解析字符串时,都会将元素添加到resultsList中。我的目标是使用这个理论上的try catch块来获取所有异常的索引,如果它们抛出错误,则将它们从resultsList中删除。 TLDR;现在,上面的代码打印出0,而我希望它打印出0和2。基本上,与其使用嵌套的try catch块,我还使用列表理解和带有i的异常处理指标来删除错误结果并仅保留好结果。我不知道这是否可行,因此是这个问题。我看过“实现嵌套try catch块的更好方法”的问题,但是它对我没有用,因为它在delphi中提供了解决方案,我不知道它是如何工作的,甚至我也不知道它是如何工作的想要我的工作。起初我以为finally块可能是我需要的,但是只有在执行catch或没有异常后才尝试运行。我需要将catch块推迟到尝试完成之前的东西,而我想不到/找到能做到这一点的东西。

你疯了吗?

现在您可能会问,这到底是什么意思?很好地想象一下,如果您遇到上述问题,而不是使用两种方法来解析字符串,则需要10或100。很快,使用嵌套try catch块进行异常处理几乎是不可能的。我见过解决方案,其中catch块调用一个自定义异常方法,然后该方法至少要处理不良的格式。看起来像这样:

try{
//bad code
}
catch{
    trysomethingelse();
}
trysomethingelse(){
//equally bad code
catch{
//ya done screwed up son
}
}

但是我不满意,因为这意味着您需要一百万个不同的方法名才能处理一个错误。试想一下,错误始终是相同的,您只需要尝试100种不同的字符串解析方法即可。如果您尝试将字符串转换为数字,它将始终是numberformatException,那么为什么仅针对同一错误就拥有一百万个catch块?我想尝试用一个理论上的catch块来做到这一点,它指定了一个在try块中发生多次的错误。

3 个答案:

答案 0 :(得分:1)

您可以执行以下操作:

 interface Parser {
       Number parse(String);
 }

 class IntegerParser implements Parser {
    @Override
    public Number parse(String) {
         // implementation here
    }
 }
 class FloatParser implements Parser {
 }

 List<Parser> parsers = asList(new FloatParser(), new IntegerParser(), ...);
 Number result = null;
 List<NumberFormatException> exceptions = new ArrayList<>();
 for (Parser parser : parsers) {
     try {
         result = parser.parse(stringToParse);
         break;
     } catch (NumberFormatException e) {
         exceptions.add(e);
     }
 }
 if (result != null) {
    // parsed ok with some parser
    // probably discard exceptions
 } else {
    // show exceptions from the list
 }

答案 1 :(得分:1)

您建立一个解析器列表/数组,然后迭代该列表,捕获每个解析器的异常。

有了Java 8方法参考,这确实很容易。首先,定义一个validate()功能接口,该接口允许引发异常:

function validate(){
    var ddlIncome = document.getElementById("income");
    var ddlExpence = document.getElementById("expense");

    var selectedValueIncome = ddlIncome.options[ddlIncome.selectedIndex].value;
    var selectedValueExpence = ddlExpence.options[ddlExpence.selectedIndex].value;

    if (selectedValueIncome != "selectincome"){
        document.getElementById("expense").disabled=true;
    }
    else if (selectedValueIncome != "selectexpence"){
        document.getElementById("income").disabled=true;
    }
}

接下来,构建您的解析器数组以尝试:

Parser

最后,一次尝试一个:

@FunctionalInterface
public interface Parser {
    Object parse(String text) throws Exception;
}

现在您可以浏览结果:

Parser[] parsers = {
        Integer::valueOf,
        Double::valueOf,
        BigInteger::new,
        BigDecimal::new
};

输出

String text = "45.8";

Object[] results = new Object[parsers.length];
for (int i = 0; i < parsers.length; i++) {
    try {
        results[i] = parsers[i].parse(text);
    } catch (Exception e) {
        results[i] = e;
    }
}

或将已解析的对象和异常放入两个不同的列表中。由你决定。

答案 2 :(得分:0)

尝试一下:

public static void test() {
    final String num = "1.0";
    final ArrayList<Object> listofResults = new ArrayList<>();
    final java.util.function.Function<String, ?>[] parseMethods = new java.util.function.Function[3];
    parseMethods[0] = Integer::parseInt;
    parseMethods[1] = Float::parseFloat;
    parseMethods[2] = Integer::parseInt;
    int[] badIndeces = IntStream.range(0, parseMethods.length).map(i -> {
        try {
            listofResults.add(parseMethods[i].apply(num));
            return -i-1;
        } catch (NumberFormatException exc) {
            return i;
        }
    }).filter(i -> i >= 0).toArray();
    for (int element : badIndeces) {
        System.out.println(element);
    }
}