当前位置: 首页 > 知识库问答 >
问题:

为什么我要在Java使用异常处理?

涂浩皛
2023-03-14

我读了很多关于Java异常处理的帖子,但我确实得到了满意的答案,为什么我要把它们放在我的代码中呢?

  1. 我想使用JRE的一些api方法,这些方法是用检查的异常进行的。所以如果我想使用它们,我需要抛出或捕获异常(例如java I/O)。这是在我的类中使用异常的合理规则吗?
  2. 我听说了这件事

Java异常处理使错误处理代码与我的业务逻辑分离

在下面的代码段中,分离错误处理的位置在哪里?

public int division(int divident, int divisor) {
int result = 0;
try {
    result = divident / divisor;
} catch (ArithmeticException e) {
    System.out.println("Divisor must not be zero !");
}
return result;
}

3.Java默认的异常处理使异常信息显示在标准输出中并终止程序。我是否自己使用异常处理来避免从我的程序中终止?

共有2个答案

吕高昂
2023-03-14

1)如果您的代码无法处理异常,您可以捕获API调用抛出的检查异常,并将它们包装在未检查异常中。确保将原始检查异常保存为新的未检查异常中的原因。

2)您的html" target="_blank">示例片段并没有将错误处理与业务逻辑分开,而是将它们组合在一起并混淆结果。在这里抛出算术异常而不是返回默认值有两个好处:a)将用来标记错误的值与有效计算结果的值区分开来太难了;b)进一步的业务逻辑步骤可能取决于在这里计算了有效值,在这种情况下,您将不得不离开当前流,您不妨为此使用异常。

3)这取决于应用程序。对于简单的控制台程序,有时最好的做法是让错误终止程序。对于web应用程序,异常通常会冒出到全局异常处理程序,终止该请求,但让其他请求继续。对于单元测试,异常会被测试运行程序捕获并记录,以便其他测试继续。

杨和蔼
2023-03-14

这是三个问题,但这不是第一次发生。:-)

>

  • 是的,您必须处理或声明它们,因为它们是检查异常。您必须这样做的原因是,调用您的代码的代码知道您的代码可能失败的方式(因为您声明了它可能引发的异常)。

    这个片段非常简单,所以分离和好处并不是那么清楚。但请考虑打开两个流,用转换代码(包括对从属方法的调用)从一个复制到另一个。最终得到一个包含10-20条语句的方法体。不是每个I/O语句都必须检查它是否工作,而是将逻辑包装在IOException处理程序中,知道任何I/O异常都将跳出主逻辑进入处理程序。

    这取决于您编写的程序类型,但通常情况下,您在最适当的级别处理异常,这通常是在程序的多个级别。最外层只处理非常非常不寻常的、不可恢复的异常,它要么让默认处理做它所做的事情,要么使用一个catch-all处理程序,该处理程序做一些类似的事情,但也可能(尝试)在其他地方记录失败(比如日志文件):

    public class MyProgram {
        public static final void main(String[] args) {
           try {
               // Run...
           }
           catch (Throwable t) {
               // Handle the fact that something went wrong here, if you can
               // Usually this would be only for really, really unusual errors,
               // otherwise you would have handled them earlier
           }
        }
    }
    

    为了强调#2中的观点,请考虑两个process方法,一个在Java中使用有异常的方法,另一个在假设的类似Java的语言中使用没有异常的方法:

    Java一号:

    private void process() {
        try (                                                // <== Main logic
            Reader fr = new FileReader(this.sourceFileName); // <== Main logic
            BufferedReader br = new BufferedReader(fr);      // <== Main logic
            Writer fw = new FileWriter(this.destFileName);   // <== Main logic
            BufferedWriter bw = new BufferedWriter(fw)       // <== Main logic
            ) {                                              // <== Main logic
            String line;                                     // <== Main logic
            while ((line = br.readLine()) != null) {         // <== Main logic
                if (shouldIncludeLine(line)) {               // <== Main logic
                    line = transformLine(line);              // <== Main logic
                    bw.write(line);                          // <== Main logic
                    bw.newLine();                            // <== Main logic
                }                                            // <== Main logic
            }                                                // <== Main logic
        }
        catch (FileNotFoundException fnfe) {                 // <== Error handling
            // Couldn't find a file                          // <== Error handling
            // (handle it)                                   // <== Error handling
        }                                                    // <== Error handling
        catch (IOException ioe) {                            // <== Error handling
            // I/O error                                     // <== Error handling
            // (handle it)                                   // <== Error handling
        }                                                    // <== Error handling
        catch (Exception e) {                                // <== Error handling
            // Something else went wrong                     // <== Error handling
            // (handle it)                                   // <== Error handling
        }                                                    // <== Error handling
    }
    

    Java式的假想语言无一例外地有一个:

    // THIS IS FAKE, PSEUDO-JAVA
    private Errors process() {
        Reader fr = new FileReader(this.sourceFileName);            // <== Main logic
        if (fr == null) {                                           // <== Error handling
            return Errors.CantOpenSource;                           // <== Error handling
        }                                                           // <== Error handling
        BufferedReader br = new BufferedReader(fr);                 // <== Main logic
    
        Writer fw = new FileWriter(this.destFileName);              // <== Main logic
        if (fw == null) {                                           // <== Error handling
            br.close();                                             // <== Error handling
            return Errors.CantOpenDest;                             // <== Error handling
        }                                                           // <== Error handling
        BufferedWriter bw = new BufferedWriter(fw)                  // <== Main logic
    
        String line;                                                // <== Main logic
        while ((line = br.readLine()) != IO.END_OF_FILE) {          // <== Main logic
            if (line == null) {                                     // <== Error handling
                br.close();                                         // <== Error handling
                bw.close();                                         // <== Error handling
                return Errors.CantRead;                             // <== Error handling
            }
            if (shouldIncludeLine(line)) {                          // <== Main logic
                line = transformLine(line);                         // <== Main logic
                if (bw.write(line) == -1 || bw.newLine() == -1) {   // <== Main logic (plus some error handling)
                    br.close();                                     // <== Error handling
                    bw.close();                                     // <== Error handling
                    return Errors.CantWrite;                        // <== Error handling
                }
            }
        }
    
        bw.close();
        br.close();
        return Errors.Success;
    }
    

    注意事项:

    • 主逻辑如何充斥着错误处理,使其更难阅读和遵循。
    • 特殊的“错误”返回值对于任何可能具有某种故障模式的方法都是必需的。我们必须在process中添加一个,然后从new fileReader等中检查null,并从read和write ops等中检查-1,等等

    如果你感兴趣,这里有一个完整版的Java计划和完整版的非真正的Java计划:

    Java:

    import java.io.*;
    
    public class Example
    {
        private String sourceFileName;
        private String destFileName;
    
        public static void main (String[] args) throws java.lang.Exception
        {
            try {
                new Example(args[0], args[1]).process();
            }
            catch (ArrayIndexOutOfBoundsException npe) {
                // This is a bit of an exaggeration, I'd check in advance, since the user not
                // supplying arguments isn't really an "exceptional" condition.
                System.out.println("Usage: java Example [source file name] [dest file name]");
            }
        }
    
        public Example(String src, String dest) {
            // Similar, these checks would probably be assertions, but I'm making a point...
            if (src == null || src.length() == 0) {
                throw new IllegalArgumentException("src must be non-null and non-blank");
            }
            if (dest == null || dest.length() == 0) {
                throw new IllegalArgumentException("dest must be non-null and non-blank");
            }
            this.sourceFileName = src;
            this.destFileName = dest;
        }
    
        private void process() {
            try (                                                // <== Main logic
                Reader fr = new FileReader(this.sourceFileName); // <== Main logic
                BufferedReader br = new BufferedReader(fr);      // <== Main logic
                Writer fw = new FileWriter(this.destFileName);   // <== Main logic
                BufferedWriter bw = new BufferedWriter(fw)       // <== Main logic
                ) {                                              // <== Main logic
                String line;                                     // <== Main logic
                while ((line = br.readLine()) != null) {         // <== Main logic
                    if (shouldIncludeLine(line)) {               // <== Main logic
                        line = transformLine(line);              // <== Main logic
                        bw.write(line);                          // <== Main logic
                        bw.newLine();                            // <== Main logic
                    }                                            // <== Main logic
                }                                                // <== Main logic
            }
            catch (FileNotFoundException fnfe) {                 // <== Error handling
                // Couldn't find a file                          // <== Error handling
                // (handle it)                                   // <== Error handling
            }                                                    // <== Error handling
            catch (IOException ioe) {                            // <== Error handling
                // I/O error                                     // <== Error handling
                // (handle it)                                   // <== Error handling
            }                                                    // <== Error handling
            catch (Exception e) {                                // <== Error handling
                // Something else went wrong                     // <== Error handling
                // (handle it)                                   // <== Error handling
            }                                                    // <== Error handling
        }
    
        private boolean shouldIncludeLine(String line) {
            return line.length() != 0;
        }
    
        private String transformLine(String line) {
            return line.toUpperCase();
        }
    }
    

    Java式的假想语言无一例外地有一个:

    // THIS IS FAKE, PSEUDO-JAVA WITHOUT EXCEPTIONS, IT ISN'T REAL
    import java.io.*;
    
    public class Example
    {
        private String sourceFileName;
        private String destFileName;
    
        private enum Errors {
            Success,
            CantOpenSource,
            CantOpenDest,
            CantRead,
            CantWrite
        }
    
        public static void main (String[] args) throws java.lang.Exception
        {
            if (args.length < 2) {
                System.out.println("Usage: java Example [source file name] [dest file name]");
            }
            if (args[0] == null || args[0].length() == 0) {
                throw new IllegalArgumentException("src must be non-null and non-blank");
            }
            if (args[1] == null || args[1].length() == 0) {
                throw new IllegalArgumentException("dest must be non-null and non-blank");
            }
            switch (new Example(args[0], args[1]).process()) {
                case Errors.CantOpenSource:
                    // Handle it
                    break;
                case Errors.CantOpenDest:
                    // Handle it
                    break;
                case Errors.CantRead:
                    // Handle it
                    break;
                case Errors.CantWrite:
                    // Handle it
                    break;
            }
        }
    
        public Example(String src, String dest) {
            // Not how now this constructor is trusting that it is called with valid arguments
            this.sourceFileName = src;
            this.destFileName = dest;
        }
    
        private Errors process() {
            Reader fr = new FileReader(this.sourceFileName);            // <== Main logic
            if (fr == null) {                                           // <== Error handling
                return Errors.CantOpenSource;                           // <== Error handling
            }                                                           // <== Error handling
            BufferedReader br = new BufferedReader(fr);                 // <== Main logic
    
            Writer fw = new FileWriter(this.destFileName);              // <== Main logic
            if (fw == null) {                                           // <== Error handling
                br.close();                                             // <== Error handling
                return Errors.CantOpenDest;                             // <== Error handling
            }                                                           // <== Error handling
            BufferedWriter bw = new BufferedWriter(fw)                  // <== Main logic
    
            String line;                                                // <== Main logic
            while ((line = br.readLine()) != IO.END_OF_FILE) {          // <== Main logic
                if (line == null) {                                     // <== Error handling
                    br.close();                                         // <== Error handling
                    bw.close();                                         // <== Error handling
                    return Errors.CantRead;                             // <== Error handling
                }
                if (shouldIncludeLine(line)) {                          // <== Main logic
                    line = transformLine(line);                         // <== Main logic
                    if (bw.write(line) == -1 || bw.newLine() == -1) {   // <== Main logic (plus some error handling)
                        br.close();                                     // <== Error handling
                        bw.close();                                     // <== Error handling
                        return Errors.CantWrite;                        // <== Error handling
                    }
                }
            }
    
            bw.close();
            br.close();
            return Errors.Success;
        }
    
        private boolean shouldIncludeLine(String line) {
            return line.length() != 0;
        }
    
        private String transformLine(String line) {
            return line.toUpperCase();
        }
    }
    

  •  类似资料:
    • 问题内容: 要编译此代码,我可以: 将我的通话置于try / catch块中,或 已经声明它可以抛出一个。 为什么我必须这样做? (示例代码来自Kathy Sierra的SCJP书 。) 我知道引发的异常是已检查的异常,因此我必须处理它,但是在什么情况下需要引发此异常? 问题答案: 如果以一种可以引发检查异常的方式声明方法(不是的子类),则调用该方法的代码必须在一个块中调用它,否则调用者方法必须声

    • 问题内容: 这是我运行的行: 这是我从LogCat获得的异常: 错误/AndroidRuntime(311):java.lang.NoClassDefFoundError:javax.sound.sampled.AudioSystem 这是我一年前编写的旧程序,然后运行良好。为什么会出现此异常,我该如何解决? 问题答案: 是JavaSound的一部分,而JavaSound是桌面JVM / SDK的

    • 我有两个函数引发异常: 若在lambda表达式中使用花括号组合这些函数调用,则需要try/catch来处理异常。 然而,若我合并到for循环中,就可以了。 我认为由于创建了新的闭包(使用括号),所以需要try/catch,但在for循环中,它不需要。我只使用for循环解决了这个问题,但我想知道为什么会发生这种情况。

    • 问题内容: 当您使用Exception类扩展一个类(用于创建新的异常)时,会收到警告,提示您有一个。我知道这在序列化和反序列化过程中起着重要的作用,但是何时需要序列化我的Exception?谁能给我一个实际的案例,让我的自定义异常类具有序列化和反序列化? 问题答案: 这是因为所有异常的根类都实现了接口。默认情况下,所有异常都是可序列化的,这是一种语言设计决策,因为作者希望异常能够在没有任何特殊配置

    • 问题内容: 我刚开始,最近经历了一个ODM框架。 在文档上,我找不到为什么需要使用。我可以给出的一个原因是,我们可以从定义应用程序架构。 我正在寻找更多可能的原因,以及吸引我使用的需求。 请列出所有可能的优点和使用理由/需要。 问题答案: 主要优势是相对于纯mongo的抽象。 来自SQL数据库类型的许多开发人员对于使用未定义结构的动态集合感到非常不舒服。因此, 模式 首先可以帮助您。 此外,它实现

    • 问题内容: 直接的答案是因为s接口被指定为不会引发异常。但是为什么呢? 或换句话说:我必须依赖可以引发异常的函数。从理论上讲,这不应该发生。但是,如果发生这种情况,我希望它脱离我正在使用的整个函数(在中)。即我希望它的行为就像发生未处理的异常一样。 似乎这不可能以一种显而易见的自然方式进行(因为如果接口说它不能抛出异常,就不会)。 我该如何解决?用丑陋的try / catch并打印出异常,并希望我