Java 在try-catch块中放入多少代码

Java 在try-catch块中放入多少代码,java,try-catch,Java,Try Catch,对于在try/catch块中放入多少代码,是否有“最佳实践” 我在下面发布了3种不同的场景 我没有在每个catch块中包括行为,也没有包括finally块。这是为了提高观众的可读性。假设每个捕获都有不同的动作。并假设最终将关闭流。只是想为未来的读者创建一个易于阅读的示例 控件,无try/catch 为每个需要的位置使用1try/catch编码 整个代码块周围只有1个try/catch 什么是公认的最佳实践以及为什么? 情景1 不带的代码try/catch,仅用于控制 BufferedR

对于在
try/catch
块中放入多少代码,是否有“最佳实践”

我在下面发布了3种不同的场景

我没有在每个
catch
块中包括行为,也没有包括finally块。这是为了提高观众的可读性。假设每个捕获都有不同的动作。并假设
最终将关闭流。只是想为未来的读者创建一个易于阅读的示例

  • 控件,无
    try/catch
  • 为每个需要的位置使用1try/catch编码
  • 整个代码块周围只有1个try/catch
  • 什么是公认的最佳实践以及为什么?


    情景1

    不带的代码try/catch,仅用于控制

        BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            Object object = new Object();
            this.doSomething(object);
        }
        bufferedReader.close();
    

    场景2

    使用try/catch块为每个需要的地方编码

        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader("somepath"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        String line;
        try {
            while ((line = bufferedReader.readLine()) != null) {
                Object object = new Object();
                this.doSomething(object);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    

    场景3

    用1try/catch围绕整个代码块进行编码

        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                Object object = new Object();
                this.doSomething(object);
            }
            bufferedReader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    

    我认为这和在方法中输入多少代码是相似的。尝试编写Try/catch/finally,它只占用一个屏幕。我想说,将整个方法体包装到try{}块中不是问题,但是如果代码太长,您应该将代码分成几个方法。

    您使用一个try/catch的示例是没有意义的,因为您只需打印堆栈跟踪并继续,因为您已经知道这将是一个失败。您还可以尝试/捕获整个过程,或者在方法签名中添加抛出异常,并让调用方法决定出了什么问题


    另外,不要担心在try/catch中挤压太多。您始终可以将该代码提取到另一个方法中。可读性是编程最重要的一个方面。

    您应该根据以下标准确定尝试/捕获的范围:

    • 您是否需要根据异常的来源做不同的事情
    • 您是否需要根据抛出的异常执行不同的操作
    • 当抛出给定的异常时,需要跳过哪些代码(aka是“无效的”)

    回答这些问题将使您能够确定任何try/catch块的适当范围。

    第三个选项当然是最好的。您不希望try/catch块变得笨拙,但在本例中,它足够短,您不需要像在第二个选项中那样对其进行分割。

    我会在try/catch中放入尽可能少的内容

    这允许您非常轻松地将代码片段移动到单独的方法中,这是一种良好的编码实践(遵守单一责任原则;请参阅Robert C.Martin的《干净的代码:敏捷软件工艺手册》一书)

    另一个优点是,您可以快速确定哪些代码实际上可以引发异常

    不过,场景2似乎有点极端,而且由于方法非常小,场景3似乎是最佳选择


    但是,您需要在finally块中使用“close”语句。

    您应该使用第三种场景

    BufferedReader bufferedReader;
    try {
        bufferedReader = new BufferedReader(new FileReader("somepath"));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            Object object = new Object();
            this.doSomething(object);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (bufferedReader != null)
            bufferedReader.close(); 
    }
    
    如果bufferedReader遇到异常,那么在第二个场景中创建时,如果您尝试对其执行
    readLine()
    ,它将遇到另一个异常。为同一问题提出多个异常没有意义

    您还应该在finally块中关闭bufferedReader

    BufferedReader bufferedReader;
    try {
        bufferedReader = new BufferedReader(new FileReader("somepath"));
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            Object object = new Object();
            this.doSomething(object);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (bufferedReader != null)
            bufferedReader.close(); 
    }
    

    而不是情景2。如果FileReader或BufferedReader构造函数抛出,则BufferedReader将为null,但下一个try/catch仍将执行。因此,您将在bufferedReader.readLine获得一个(未捕获的)异常——一个NullPointerException。在场景1和场景3之间,我通常更喜欢3,因为它不需要调用方捕捉。顺便说一下,您不需要显式地捕获FieloToFunExtPosits,因为它继承了IOExt,因此catch块将同时捕获这两个值。

    < P>我认为<代码>异常< /代码>是一个非编码返回的结果类型。所以,当我使用try-catch部分时,我试图回答问题

  • 我应该在这里处理意外的结果,还是应该在更高的级别上传播它
  • 我应该处理哪些意外结果
  • 如何处理
  • 在95%的情况下,我没有超过第一点,所以我只是传播错误


    对于文件处理,我使用
    try with resources
    重新抛出
    IOException
    并抛出新的RuntimeException(e)

    这是一个意见问题。这些模式我都见过很多

    模式1只有在您的方法可以抛出expetions并在调用方链上处理它时才是好的。这通常是可取的。但是,由于
    close
    调用不在
    finally块中,因此可能无法调用它。至少,使用
    try finally

    模式2并不好,因为如果第一个try-catch块处理异常,那么该方法的其余部分就没有用了

    模式3可以,但不是很好,因为打印堆栈跟踪隐藏了操作失败的事实。如果调用方认为操作发生了,而实际上没有发生,该怎么办。此外,
    close
    s可能没有发生,这可能导致程序失败

    在伪代码中,模式3的这种变体更好:

    Declare Streams, connections, etc.
    try
        Initialize streams, connections, etc,
        Do work.
    catch (optional)
        Catch and handle exceptions.
        Do not simply log and ignore.
    finally
        Close connections and streams in reverse order.
        Remember, closing these objects can throw,
            so catch exceptions the close operation throws.
    End.
    
    如果您使用的是Java 7,请使用try with参考资料:

    try (BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"))) {
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            Object object = new Object();
            this.doSomething(object);
        }
    }
    

    IOException
    s冒泡到调用方

    jtahlborn已经有了正确的答案

    不幸的是,有时候,适当的异常处理可能非常臃肿。 如果需要,人们应该准备好处理它

    另一种可能的场景是嵌套的try-catch块

    考虑:

    BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"));
    try {
            String line;
    
            while ((line = bufferedReader.readLine()) != null) {
                Object object = new Object();
                try {
                   this.doSomething(object);
                } catch (InvalidArgumentException iae) {
                   throw new RuntimeErrorException("Failed to process line " + line + ", iae);
                } catch (ParserWarning e) {
                   e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            bufferedReader.close();
        }
    

    我认为最好为您想要捕获的异常放置一个try语句和多个捕获。更好的可读性。