为什么包装异常仍然会在添加抛出时请求try-catch?

时间:2015-07-24 19:20:54

标签: java exception

我正在自己的个人图书馆中使用SikuliX's API。我的想法是在外部项目中单独引用我的库,其中包含了我需要的SikuliX部分。

现在,SikuliX抛出一个FindFailed异常,我需要它。我试着这样做:

public class FindFailed extends org.sikuli.script.FindFailed {
    FindFailed(String msg) { super(msg); }
}

这似乎有道理。但是,当尝试在其中一个方法中使用throws语句时:

import org.mylibrary.exceptions.FindFailed;

public static boolean clickFinishButton() throws FindFailed {
    pattern = PatternManager.loadPattern("my-image.png");

    screen.wait(pattern, 10);
    region = screen.exists(pattern);
    region.click(pattern);

    return true;
}

我仍然收到Unhandled exception type FindFailed警告。将其更改回原始org.sikuli.script.FindFailed当然会有效,但在外部项目中使用try-catch将需要我重新添加相关的SikuliX jar文件。

我想做的是简单地包装SikuliX抛出的FindFailed异常,并在我的库内部和外部使用它。

所有这一切的主要目标是使用我自己的其他方法来包装另一个API,这样当我引用这个库时,后面的项目也不必引用SikuliX的jar。

- - - - My Library - - - <—————— External Project
|                      |
|        SikuliX       |
- - - - - - - - - - - - 

就像现在一样,我要求做以下事情:

- - - - My Library - - - <—————— External Project
|                      |                |
|        SikuliX       |                |
- - - - - - - - - - - -                 v
                                  SikuliX (Again)

到目前为止,我改变了以下似乎有效的方法。

public class FindFailed extends Exception {
    public FindFailed(Throwable cause) { super(cause); }
}

我现在不延长任何第三方例外情况。而我继续做以下事情:

public static boolean clickNewScan() throws FindFailed {
    pattern = PatternManager.loadPattern("my-image.png");   
    region = screen.exists(pattern);
    try {
        screen.wait(pattern, 60);
        region.click(pattern);
    } catch (org.sikuli.script.FindFailed e) {
        throw new FindFailed(e);
    }
    return true;
}

2 个答案:

答案 0 :(得分:5)

您可以通过将SikuliX中的所有调用包装在自己的接口中来完成此操作。我不知道SikuliX,所以我会做一个玩具示例。

package third.party.library;

public class Foo {
    public void doSomething() throws ThirdPartyException {
        // Their code
    }
}

好的,所以你想要包装这个功能而不依赖于他们的库。

package juxhin;

public interface FooBehavior {
    public void doSomething() throws MyException;
}

然后,当您需要他们的行为时,您可以使用自己的实现:

package juxhin; // YOU write this class

public class ThirdPartyFooBehavior implements FooBehavior {
    private final Foo foo;

    public FooThirdPartyFooBehavior(Foo theirObject) {
        this.foo = theirObject;
    }

    @Override
    public void doSomething() throws MyException {
        try {
            foo.doSomething();
        } catch (ThirdPartyException e) {
            throw new MyException(e);
        }
    }
}

一旦你将你的库包装在你自己的所有接口之后,那么你的类只依赖于你自己的接口,这意味着你不必担心它们的异常。只要您使用非依赖实现重新实现这些接口,它们的库就可以完全删除。

请注意,MyException 不应延长third.party.library.ThirdPartyException,因为这对您的问题没有帮助;它应该使用Exception(Throwable cause)构造函数并将其从org.sikuli.script类层次结构中删除。

但最重要的是,您仍然必须以某种方式包含SikuliX中包含的代码。这就是Maven之类的工具存在的原因,因此添加对jar的引用非常简单。例如,如果您的jar依赖于SikuliX,那么当您告诉您的新项目使用您的jar时,它会自动包含SikuliX引用而无需您执行任何操作。你最终会得到像这样的依赖树,它会自动为你完成所有这些工作:

Maven screenshot

我个人使用Maven但是还有其他选项,例如IvyGradle,它们做同样的事情 - 我不是在这里提倡任何特定的工具,只是提倡使用任何依赖工具。

答案 1 :(得分:1)

从你不拥有的课程扩展永远不是一个好主意,应该避免。此外,它会使处理你的异常的人仍然拥有包含org.sikuli.script.FindFailed的jar。

更好的方法是将这样的异常包装起来:

public class MyFindFailedException extends Exception {
    MyFindFailedException(String message, Exception cause) {
        super(message, cause);
    }
}

然后像这样使用它:

public static boolean clickFinishButton() throws MyFindFailedException {
  try {
    pattern = PatternManager.loadPattern("my-image.png");

    screen.wait(pattern, 10);
    region = screen.exists(pattern);
    region.click(pattern);

    return true;
  } catch (FindFailed e) {
    throw new MyFindFailedException("something went wrong", e);
  }
}