使用try / catch而不是多个IF语句更好吗?

时间:2010-03-09 13:08:15

标签: java try-catch

在Java中使用try/catch块而不是使用多个If语句来检查用户输入是否更好,更便宜或更具可读性?

解析Date字符串时的示例,使用try / catch块直接解析而不是编写查找非法字符的多个语句不是更好。

在另一个例子中,假设我想要读取文件或流,而不是使用Scanner,我只是强制该方法并等待发生异常。

这是一种健康的编程方法吗?它在虚拟机上更便宜吗?

更新
这是我在using DateFormat exception时的意思的一个例子,有时它可能是一个真正的问题来捕获错误,当这样做时,你能保证你的复杂(通常是不可读的)代码容易出错吗?

8 个答案:

答案 0 :(得分:29)

将异常用于流量控制是一种不好的做法。

一些引言:

  

因为异常是为特殊情况而设计的   在JVM实现尝试的情况下,很少(如果有的话)   优化他们的表现。创建通常很昂贵,   抛出,并捕捉异常。

  

存在无关的错误,成语   可以无声地失败并掩盖错误,使调试变得非常复杂   过程

更新: 正如所说的那样(我记得我在Josh Bloch的博客中也发现了相同的声明)使用流控制的异常就像使用GOTO一样。你可以阅读有趣的Dijkstra文章,了解为什么GOTO是坏的。

答案 1 :(得分:4)

一般而言,例外情况是指......好的,特殊事件。 If适用于在正常事件过程中可能发生的事情。

通常情况下,如果您想处理一个没有良好本地解决方案的案例,请使用例外将其向上传播给可以更好地处理它的人。这比if-else成本高得多,这是不滥用它的另一个原因。第三,恕我直言同样重要的问题是可读性:在throw之后继续执行流程的地方比阅读一系列if语句要困难得多。

如果您想在本地处理案例,大多数情况下最好使用简单的if

答案 2 :(得分:1)

例外情况适用于例外个案。使程序逻辑依赖于被抛出的异常是一个坏主意。

答案 3 :(得分:1)

使用Exception代替If会更昂贵,因为编译器和jvm将有更多的工作和困难来优化这些块的控制流,并且通常例外是异常。

答案 4 :(得分:1)

异常对性能有好处,因为它们适用于特殊情况,因此需要权衡使非异常情况更快,但代价是使异常变慢。话虽如此,如果没有对特定情况进行基准测试,就不可能说出在特定情况下差异是否显着。

但还有另一个更重要的考虑因素:你应该避免重复逻辑。复制日期解析逻辑以避免异常绝对不是好事。不幸的是,Java没有在.NET框架中找到的TryParse()方法,它们允许您使用框架的解析逻辑进行健全性测试而无例外。

在这种情况下,我倾向于使用异常,除非探查器已将其识别为性能瓶颈。但是对于更简单的测试(空值,文件结尾),我强烈避免使用异常作为if子句的替代。

答案 5 :(得分:0)

我认为try catch捕获异常会更加昂贵,而if语句可能看起来更干净。

答案 6 :(得分:0)

抛出异常时,消息堆栈将复制到新的Exception对象中,以启用调试和printStackTrace()。这很贵。

如果您的内容越来越多,请考虑流量控制模式,例如策略,状态和命令模式。

答案 7 :(得分:0)

只有在抛出异常时尝试catch才是昂贵的,我认为这是因为堆栈跟踪创建。我运行以下基准来验证这一点:

 public class TestTryCatchVsIfElseVsNoBlock
 {
    private static final int numberOfIteration = 1000000;

    public static void main(String[] args)
    {

    //measureExIfElse
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureIfElse(null);
    }
    long start = System.nanoTime();
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureIfElse(null);
    }
    final long ExIfElse = (System.nanoTime() - start);



    //measureExTryCatch
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureTryCatch(null);
    }
    start = System.nanoTime();
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureTryCatch(null);
    }
    final long ExTryCatch = (System.nanoTime() - start);


    //measureIfElse
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureIfElse("Nitin");
    }
    start = System.nanoTime();
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureIfElse("Nitin");
    }
    final long IfElse = (System.nanoTime() - start);


    //measureTryCatch
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureTryCatch("Nitin");
    }
    start = System.nanoTime();
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureTryCatch("Nitin");
    }
    final long TryCatch = (System.nanoTime() - start);


    //WithoutAnyBlock
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureWithoutAnyBlock("Nitin");
    }
    start = System.nanoTime();
    for (int i = 0; i < numberOfIteration; i++)
    {
        measureWithoutAnyBlock("Nitin");
    }
    final long WithoutAnyBlock = (System.nanoTime() - start);

    System.err.println("ExIfElse: "+ ExIfElse/(float)numberOfIteration); // 3.563198
    System.err.println("ExTryCatch: "+ ExTryCatch/(float)numberOfIteration); // 15.924681
    System.err.println("IfElse: "+ IfElse/(float)numberOfIteration); // 1.683819
    System.err.println("TryCatch: "+ TryCatch/(float)numberOfIteration); // 1.507893
    System.err.println("WithoutAnyBlock: "+ WithoutAnyBlock/(float)numberOfIteration); // 1.750418

}

private static int i = 0;
private static void measureTryCatch(String s)
{
    try
    {
        s.length();         
    }
    catch (Exception e)
    {
        ++i;
    }
}

private static void measureWithoutAnyBlock(String s)
{
    s.length();
}

private static void measureIfElse(String s)
{
    if(s!=null)
    {
        s.length();
    }
    else
    {
        ++i;
    }
}

}