Java 链式异常的优点是什么

Java 链式异常的优点是什么,java,exception-handling,Java,Exception Handling,我不理解在代码中使用链式异常的好处 考虑到,如果程序员知道可能遇到ResourceLoadException,为什么不捕获相同的异常而不是SQLException?否则,程序员可以在同一代码中捕获这两个异常,而不是抛出一个新的Throwable实例 我认为该示例的原因是作者希望创建一个统一的接口,该接口不依赖于特定的底层系统,如SQL。因此,他将异常转换为更一般的形式,使实际实现对业务逻辑透明 但是,在某些情况下,可能需要传播类似SQLException的错误。在需要根据抛出的异常采取不同操作的

我不理解在代码中使用链式异常的好处


考虑到,如果程序员知道可能遇到
ResourceLoadException
,为什么不捕获相同的异常而不是
SQLException
?否则,程序员可以在同一代码中捕获这两个异常,而不是抛出一个新的
Throwable
实例

我认为该示例的原因是作者希望创建一个统一的接口,该接口不依赖于特定的底层系统,如SQL。因此,他将异常转换为更一般的形式,使实际实现对业务逻辑透明

但是,在某些情况下,可能需要传播类似SQLException的错误。在需要根据抛出的异常采取不同操作的地方,这将非常有用

任何人都可以提供有关链式例外需要的信息吗?

这篇文章说得很好:

异常链接允许您将一种异常类型映射到另一种异常类型,以便方法可以抛出与方法本身在同一抽象级别定义的异常,而不会丢弃重要的调试信息

也就是说,如果您有一个从数据库加载某个对象的方法,那么您可能更希望使用一些
ResourceLoadException
(更接近方法抽象级别),而不是低级
SQLException
,即使这是问题的原始根源。但是,如果只是捕获
SQLException
并抛出
ResourceLoadException
,则可能会丢失重要的调试信息

因此,链接异常是一个很好的选择。您抛出一个非常适合特定方法的“高级”异常,但将其与导致该异常的异常链接起来

否则,程序员可以在同一代码中捕获这两个异常,而不必抛出新的可丢弃实例?


我不太明白你的道理。关键是他不需要在这个抽象级别上担心
SQLException

优点是调用方只需处理
ResourceLoadException
,而不必处理
SQLException
。这样,如果您以后将数据存储更改为位于文件中,则访问该文件可能会导致
IOException
。您不必返回并更改调用方处理的异常类型。这对调用者很有用,因为调用者将以相同的方式处理任一异常。

加载资源的调用者不需要知道如何加载这些资源的确切细节,或者至少不关心失败原因的细节。(请记住,可能不是您编写了
loadResources
,也可能是其他人需要使用loadResources方法)

调用loadResource时,您应该关心的是它可能会引发ResourceLoadException。并不是因为SQLException导致实现细节失败——这也可能随着时间的推移而改变,稍后可能会有人决定从其他地方加载可能也会失败的资源

您只需要加载一些资源,需要处理它是否失败,而不需要处理潜在的MainframeHasCrashedException、FileNotFoundException以及加载这些资源可能失败的十几个其他原因

现在,当某些东西确实失败时,可以很方便地找到导致失败的原始异常,例如SQLException,这样就可以通过检查stacktrace查找日志文件或类似文件来找出错误的原因


您也不应该试图在此处捕获异常,如果loadResources也可能引发其他异常,例如UnauthorizedException,则在调用loadResources时,您可能不希望处理该异常-您可能希望将该异常传播到可以处理UnauthorizedException的其他调用方(可能会提示用户提供一些凭据)。捕获(异常e)会吞掉您在那里无法处理的未经验证的异常。

第一个好处是封装。ResourceLoader可能是一个包含多个实现的接口(例如,一个从数据库加载资源,而另一个从文件系统加载资源),其中在运行时选择要使用的实现。然后调用方应该不知道加载资源失败的根本原因,但可能仍希望对资源加载失败作出反应。如果接口声明要引发调用方可能希望以不同方式响应的两个不同异常,这一点尤其有用(例如,TransentResourceLoadFailureException(重试可能成功)和PermanentResourceLoadFailureException(已知重试未成功)

异常链接的第二个好处是,链中的每个异常可能有不同的消息,这允许包含用于调试的附加信息。在您的情况下,请注意ResourceLoadException的消息包含无法加载的资源的名称,但不能保证将其包含在SQLException中n、 但可能需要重现该问题(某些数据库并不确切知道具体的错误消息)


这些好处是以编写和维护catch块为代价的。您应该根据具体情况决定这些好处是否证明了成本的合理性。

为什么会出现链异常?

我们需要链接异常以使日志可读

以下面的例子为例:1.无链接和2.链接,例外,以感受差异

创建以下异常

    class NoLeaveGrantedException extends Exception {

        public NoLeaveGrantedException(String message, Throwable cause) {
            super(message, cause);
        }

        public NoLeaveGrantedException(String message) {
            super(message);
        }
    }

    class TeamLeadUpsetException extends Exception {

        public TeamLeadUpsetException(String message, Throwable cause) {
            super(message, cause);
        }

        public TeamLeadUpsetException(String message) {
            super(message);
        }
    }

    class ManagerUpsetException extends Exception {

        public ManagerUpsetException(String message, Throwable cause) {
            super(message, cause);
        }

        public ManagerUpsetException(String message) {
            super(message);
        }
    }

    class GirlFriendOfManagerUpsetException extends Exception {

        public GirlFriendOfManagerUpsetException(String message, Throwable cause) {
            super(message, cause);
        }

        public GirlFriendOfManagerUpsetException(String message) {
            super(message);
        }
    }
现在使用它们

1.无链接

    public class MainClass {

        public static void main(String[] args) throws Exception {
            getLeave();
        }

        static void getLeave() throws NoLeaveGrantedException {
            try {
                howIsTeamLead();
            } catch (TeamLeadUpsetException e) {
                e.printStackTrace();
                throw new NoLeaveGrantedException("Leave not sanctioned.");
            }
        }

        static void howIsTeamLead() throws TeamLeadUpsetException {
            try {
                howIsManager();
            } catch (ManagerUpsetException e) {
                e.printStackTrace();
                throw new TeamLeadUpsetException(
                            "Team lead is not in good mood");
            }
        }

        static void howIsManager() throws ManagerUpsetException {
            try {
                howIsGirlFriendOfManager();
            } catch (GirlFriendOfManagerUpsetException e) {
                e.printStackTrace();
                throw new ManagerUpsetException("Manager is in bad mood");
            }

        }

        static void howIsGirlFriendOfManager() 
             throws GirlFriendOfManagerUpsetException {
            throw new GirlFriendOfManagerUpsetException(
             "Girl friend of manager is in bad mood");
        }
    }
    public class MainClass {

        public static void main(String[] args) throws Exception {
            getLeave();
        }

        static void getLeave() throws NoLeaveGrantedException {
            try {
                howIsTeamLead();
            } catch (TeamLeadUpsetException e) {
                throw new NoLeaveGrantedException("Leave not sanctioned.", e);
            }
        }

        static void howIsTeamLead() throws TeamLeadUpsetException {
            try {
                howIsManager();
            } catch (ManagerUpsetException e) {
                throw new TeamLeadUpsetException(
                           "Team lead is not in good mood", e);
            }
        }

        static void howIsManager() throws ManagerUpsetException {
            try {
                howIsGirlFriendOfManager();
            } catch (GirlFriendOfManagerUpsetException e) {
                throw new ManagerUpsetException("Manager is in bad mood", e);
            }

        }

        static void howIsGirlFriendOfManager() 
           throws GirlFriendOfManagerUpsetException {
            throw new GirlFriendOfManagerUpsetException(
              "Girl friend of manager is in bad mood");
        }
    }
    com.bskyb.svod.autoingest.GirlFriendOfManagerUpsetException: Girl friend of manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsGirlFriendOfManager(MainClass.java:61)
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:52)
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:43)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    com.bskyb.svod.autoingest.ManagerUpsetException: Manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:55)
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:43)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    com.bskyb.svod.autoingest.TeamLeadUpsetException: Team lead is not in good mood
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:46)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    Exception in thread "main" com.bskyb.svod.autoingest.NoLeaveGrantedException: Leave not sanctioned.
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:37)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    Exception in thread "main" com.bskyb.svod.autoingest.NoLeaveGrantedException: Leave not sanctioned.
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:36)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    Caused by: com.bskyb.svod.autoingest.TeamLeadUpsetException: Team lead is not in good mood
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:44)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        ... 1 more
    Caused by: com.bskyb.svod.autoingest.ManagerUpsetException: Manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:52)
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:42)
        ... 2 more
    Caused by: com.bskyb.svod.autoingest.GirlFriendOfManagerUpsetException: Girl friend of manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsGirlFriendOfManager(MainClass.java:58)
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:50)
        ... 3 more
2.柴