JavaRush /Java 博客 /Random-ZH /异常处理中的常见错误
Ve4niY
第 14 级

异常处理中的常见错误

已在 Random-ZH 群组中发布
异常是对 Java(或任何其他)程序的正常执行流程的中断。这种违规可能是由于内存访问违规、除以零、初始化问题、执行非法指令或任何其他致命错误而发生的。Java 能够优雅地处理所有这些不需要的场景,但是当开发人员使用这些 Java 功能时,可能会出现一些问题。在本文中,我不打算讨论Java中的异常处理如何工作。我假设读者已经熟悉异常层次结构、检查异常非检查异常和运行时异常。在这里,我们将讨论您应该避免的最常见错误。
例外的利益相关者
每当执行线程被中断时,有关它的信息必须返回给程序执行器。该线程可以从屏幕、批处理任务或任何其他方式启动。所有这些触发器都会等待流中出现某种违规情况,以传输某种格式的消息。基于屏幕的触发器可以温和地让我们知道存在一些技术问题,我们应该联系支持人员寻求帮助和建议。批处理或独立 Java 程序可能期望错误报告以最终用户完全无法理解的某种日志形式出现。但商务人士需要以他们理解的语言接收消息。用户心目中可怕的NullPointerException非常烦人。有时这些错误是由于程序使用不当造成的,但有时它们是需要纠正的问题。第二个重要的利益相关者是必须处理异常引起的问题的人。这个人无法观察异常发生时程序的实际执行情况。它将依赖于两件事 - 首先,有问题的用户提供的信息,第二,发生异常时生成的某种日志。另外,分析问题的人与编写程序的人不是同一个人,因此程序开发人员必须提供足够的信息来进行分析。程序开发人员与其调试人员之间通信的唯一方式是日志。另外,有时出于安全原因,日志日志有时可能不包含异常发生时程序执行的所有实际细节。让我们看看异常处理中可能出现的错误。有些人看起来很傻,但确实有人。谁不注意它们,直到这些错误导致问题。
空异常块
这是异常处理中最不希望出现的错误之一。在这种情况下,异常将被简单地忽略。该解决方案只包含一条注释行以留下异常。 try{ }catch(SQLException sqe){ // do nothing } 在某些罕见情况下,例如在数据库关闭时的最后一个块中,可能会引发异常。在这种情况下,它们可以被忽略。 try{ }catch(SQLException sqe){ ... ... }finally{ try{ conn.close(); }catch(Exception e){ //leave it. } }
异常消息的概括不正确
这一点是主观的。捕获异常后,您可以以友好消息的形式将其报告给最终用户。当原始消息转换为一条通用消息时,很可能会丢失原始消息的细节。该消息应向最终用户传达正确的信息,以便在联系支持团队时,用户只需登录适当的日志即可提供信息。 try{ File file = new File(""); file.getCanonicalPath(); }catch(IOException ioe){ throw new Exception("File Processing Failed",ioe); } 在多层应用程序中,每一层都会捕获异常并引发新类型的异常。有时绝对有必要强制转换某种类型的异常: - 数据访问层 -> 创建 DataAccessException - 业务实现层 -> 创建 BusinessException - 应用程序服务层 -> 创建 ApplicationServiceException 一切看起来都很合乎逻辑,不是吗?这里我们可能必须在 ApplicationServiceException 和 BusinessException 之间进行选择,因为两者可以表示相同的信息。这些异常转换之一似乎是不必要的。
销毁 StackTrace 类
在将异常转换为新的特殊类型的过程中,堆栈跟踪可能会消失,从而使追踪异常的实际原因成为一场噩梦。在下面的代码中,您可以看到如何在不接收原始异常的任何信息的情况下引发新异常。 try{ File file = new File(""); file.getCanonicalPath(); }catch(IOException ioe){ throw new MyException("Problem in data reading."); }
覆盖异常原因
每条异常消息都包含有关异常原因的信息。但是,当创建新的例外时,有关旧例外的信息可能会被永久删除。这与上面的示例类似,其中 StackTrace 可能由于抛出新异常而被删除。
不搜索特定异常
有时,开发人员在处理异常时喜欢谨慎行事。有时这很容易做到。但是捕获 java.lang.Exception 而不是特定的异常是不可接受的。 try{ File file = new File(""); file.getCanonicalPath(); }catch(Exception exe){ throw new MyException("Problem in data reading."); }
不必要的接球和投掷
如果您想将异常转换为另一种类型,或者如果它可以帮助您向最终用户或分析人员提供的异常消息中添加一些信息,请捕获异常。否则,只需将它们进一步扔到方法签名中(使用 throws),而不是捕获它们。
捕获运行时异常
我建议避免捕获 RuntimeException。相反,最好捕获特定的异常并对其进行处理。
查找未经检查的异常
是否捕获未检查的异常是一个有争议的话题。NullPointerException 和 ArrayIndexOutOfBound 可能是未经检查的异常的最佳示例。您可以更改代码来处理这些情况,而不是捕获这些异常。例如,避免 NullPointerException、确保所有变量都已初始化、避免 ArrayIndexOutOfBound 异常、定义正确长度的数组等。
与异常日志记录相关的问题
该杂志将帮助第二个感兴趣的人,即分析问题的人。有时,开发人员过度使用日志文件,并在应用程序的每个级别创建日志。日志应记录异常发生的级别。似乎最佳的做法是显示发生异常的警告,建议停止或继续执行程序,并在日志中强制记录异常。
流控异常
异常是对程序正常流程的中断,这意味着您需要中断此流程并通知最终用户。如果我们添加一个作为备用线程的方法调用,将会导致巨大的维护问题。 try{ myObject.getValue(); }catch(NullPointerException npe){ alternateMethod(); }
java.lang.Exception 的普遍使用
对于任何异常,到处使用 java.lang.Exception 也不是一个好主意。相反,最好使用特定于应用程序的异常,或者最合适的标准 Java 异常。 原文:异常处理中的常见错误 翻译和配音:Ve4niY
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION