链式异常的优点是什么?

nam*_*ked 12 java exception-handling

我不明白在代码中使用链式异常的优点.

考虑来自java世界ResourceLoader示例,如果程序员知道遇到的可能性ResourceLoadException,为什么不捕获相同的异常而不是SQLException?另外,程序员可以捕获相同代码中的异常,而不是抛出新Throwable实例?

Kal*_*her 17

为什么链异常?

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

以下为例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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在使用它们

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");
        }
    }
Run Code Online (Sandbox Code Playgroud)

2.链接

    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");
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在比较日志

1.没有链接

    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)
Run Code Online (Sandbox Code Playgroud)

2.链接

    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
Run Code Online (Sandbox Code Playgroud)

  • 喜欢你的榜样展示链接的方式.好笑 (2认同)

aio*_*obe 16

任何人都可以提供有关链式异常需求的信息吗?

文章说得很好:

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

也就是说,如果你有一个方法从数据库加载一些对象,你可能更想要一些ResourceLoadException(与方法抽象级别更密切相关)而不是低级别,SQLException即使这是问题的原始来源.但是,如果你只是抓住SQLException并抛出一个ResourceLoadException,你可能会丢失重要的调试信息.

因此,链接异常是一个很好的选择.您抛出一个"高级"异常,非常适合特定方法,但将其链接到导致它的异常.

另外,程序员可以捕获相同代码中的异常,而不是抛出一个新的Throwable实例?

我不太理解你的推理.关键是他不应该担心SQLException这种抽象层次.

  • 关键是您可能有一个接口在抽象级别抛出特定的异常类型.在该接口的实现中可能需要捕获SQLException或其他.接口的全部意义在于坚持使用它,无论实现的内容是什么,都不需要改变它......如果这样做有意义的话.此外,在这种情况下,父类将不知道如何处理SQLException.它唯一需要做的就是得出结论"我们被搞砸了",打印出一个错误,让用户修复它. (3认同)
  • 对于代码更改,没有什么是错误的*,但正如我所说的那样,在这个抽象级别上必须捕获`SQLException`可能没有意义.如果有两个资源加载类:`MysqlResourceLoader`和`FileResourceLoader`并且它们共享一个公共接口`ResourceLoader`,那该怎么办?那么`loadResource`方法显然不应该被声明为抛出一个`SQLException`.(如果我给你一个`ResourceLoader`并且你不知道它的实际类型怎么办?) (2认同)

nos*_*nos 6

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

调用loadResource时你应该关心的是它可能抛出ResourceLoadException.并非由于SQLException而导致实现细节失败 - 这可能会随着时间的推移而改变,稍后某人可能会决定从其他可能失败的地方加载资源.

您只需要加载一些资源,如果失败则需要处理,并且不处理潜在的MainframeHasCrashedException,FileNotFoundException以及加载这些资源的其他十几个原因可能会失败.

现在,当某些事情失败时,使用导致失败的原始异常(例如SQLException)很方便 - 因此,通过日志文件或类似文件搜索的人可以通过检查堆栈跟踪来找出错误的原因

你也不应该试图在这里捕获Exception,如果loadResources也可以抛出其他异常,例如UnautorizedException,你可能不想在调用loadResources时处理它 - 你可能想要将该异常传播到其他可以处理UnautorizedException的调用者(并且可能会提示用户输入某些凭据).一个catch(Exception e)会吞下UnautorizedException,你实在无法处理它.


jzd*_*jzd 5

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