Java 以编程方式区分异常

Java 以编程方式区分异常,java,exception-handling,Java,Exception Handling,异常的类型通常足以正确处理它(例如,您尝试打开一个文件并获取FileNotFoundException)。但是,在某些情况下,您可能会捕获同一类型的多个异常。例如,可能由多个参数引起的IllegalArgumentException。IllegalArgumentException不会向Throwable界面(根据在线)添加任何其他方法(或公共字段),这意味着您可以依赖的唯一信息是嵌套异常(可能存在也可能不存在)和消息(供人使用) 我不喜欢扩展IllegalArgumentException以向

异常的类型通常足以正确处理它(例如,您尝试打开一个文件并获取
FileNotFoundException
)。但是,在某些情况下,您可能会捕获同一类型的多个异常。例如,可能由多个参数引起的
IllegalArgumentException
IllegalArgumentException
不会向
Throwable
界面(根据在线)添加任何其他方法(或公共字段),这意味着您可以依赖的唯一信息是嵌套异常(可能存在也可能不存在)和消息(供人使用)

我不喜欢扩展
IllegalArgumentException
以向其添加结构化信息,因为其他人必须学习新类。我不喜欢在项目中加入非常特殊的异常类。 使用message字段也是一个坏主意,因为它不是用于编程访问的

我认为,
IllegalArgumentException
应该包含诸如类函数和参数之类的细节。一般来说,定制异常应该提供额外的细节(而不仅仅是它们的类型),以便进行更细粒度的异常处理


设计异常类和处理相同类型的异常的最佳实践通常是什么?

作为一般规则,我认为理想的做法是每个“调用方可能合理希望采取的操作类型”有一个异常类。当然,对于自己的自定义异常,可以使用布尔或枚举字段提供一些额外的消歧,而不是创建琐碎的子类

在您的具体案例中,我不认为尝试处理异常是一个好主意
RuntimeException
及其子类通常表示编码问题,
IllegalArgumentException
也是如此。如果该参数是非法的,那么首先就不应该传入


如果您不确定某个参数是否有效(可能是用户输入,也可能是您不知道调用该方法的特定对象),那么更好的方法是在传递参数之前检查参数的有效性。与其说“做这个”并捕获异常,不如在调用之前问“我能做这个吗?”。

预定义的异常类确实非常通用。但是,如果您想了解有关异常的更具体的详细信息,那么您应该选择用户定义的异常。您应该创建自己的异常类,并提供任何级别的详细信息

以下是伪代码:

public class TooManyArguments extends exception{
    public String toString(){
    return ("..whatever information you want to give for this exception..")'
    }
}

当你遇到异常情况时,抛出这个类的一个实例

throw new TooManyArguments();

异常类的设计应该能够在捕获时提供所需的一切。请注意,
try/catch
语句实际上是类型开关的一种形式,因此一般来说,创建额外的异常类比在
catch
子句中嵌套过多的
if
来混淆程序逻辑更为简洁

必须指出的是,如果您想以面向对象的方式组织错误处理代码,那么catch子句不是很方便,因此需要记住不同的权衡

请注意,标准异常类确实有关于导致异常的代码片段的可用信息,尽管我不建议您基于它来处理错误逻辑

如果当前异常是在另一个异常的catch子句中引发的,则应使用
getCause()
方法提供此功能,而
getStackTrace()
应提供对引发异常时处于活动状态的调用堆栈的访问


同样,我不建议您使用此信息,除非用于调试目的。

您可以使用多个try-catch块,以确保从正确的代码段中获得正确的异常
try{someFunction(arg1,arg2,arg3);}
如果我得到由其中一个参数引起的IllegalArgumentException怎么办?我只有一个
试试
我明白你的意思了。。。也许您只是在检查args之前,不抛出异常?是的,但这只是一个特定的情况。一般来说,您应该能够从异常中获取信息,而不仅仅是它的类型。如果您遇到IAE,那就是编程错误。因此,在将所有参数交给引发异常的方法之前,请查看该方法的stacktrace并添加对所有参数的检查。