繁体   English   中英

如何仅将我的 Java 库中的异常传递给实施应用程序?

[英]How can I pass only Exceptions from my Java Library to the implementing application?

根据Gradle 文档,您可以将依赖项包含为“API”,这意味着它将传递给实现其 class 路径的应用程序。 有没有办法只传递一个单独的类/异常而不是整个依赖项?

例子

在库 A(由我编写)中,我使用的是 Open SAML Core。 库中的 Class CoolClass 引发异常 B(来自 Open SAML 核心)。 build.gradle文件包括:

dependencies {
    implementation group: 'org.opensaml', name: 'opensaml-core', version: "24.0.2"

在 Java 应用程序 C 中,我正在实现库 A。如果我在我的应用程序中使用 CoolClass,那么gradle build会给我以下错误:

/ApplicationC/src/main/java/com/sorry/CoolClass.java:10: error: cannot access ExceptionB
                                           .someMethod();
                                                       ^
  class file for org.opensaml.core.xml.io.ExceptionB not found

有没有办法只传递该异常,而不是将整个库包含在我的应用程序的 class 路径中?

不是真的,但你的计划(“只包括这件事”)是错误的解决方案。

您遇到的一般原则是“传递依赖”。

项目 A 依赖于项目 B。但是,B 又依赖于 C ... 那么 A 现在是否依赖于 C?

传递依赖有两种“风格”:导出的和非导出的。

项目 B 是一大堆代码,但至关重要的是,其中一些代码是“可见的”。 具体来说,公开签名

如果项目 B 的 API (A 可以看到)包括public List<String> getNames() ,这意味着 List 依赖现在也是 A 需要的,否则它根本无法与此方法交互。 幸运的是, List 是java.util.List ,每个人都有,所以这不是问题,但想象一下它不是java.*空间中的类型。 为了使这项工作,您导出. 而且,这意味着无论何时您在一个公共签名中使用您的依赖项之一中的任何类型,您现在都已强制导出该依赖项。

这就是您在这里所做的,通过声明throws SomethingSpecificFromOpenSAML ,您现在必须导出 openSAML。

解决方案:只是..不要扔那个

如果这是您在公共签名中唯一使用的东西,那么答案似乎很明显。 别再扔了,你的代码是错误的。 您不应在throws语句中声明任何实现细节,如果您无意在此处“导出”OpenSAML,那么显然它是一个实现细节。

相反,抓住它并将其作为其他东西扔掉。 或者,保持原样,但声明抛出异常:

// Example 1
public void saveGame() throws OpenSamlException {
  doSamlStuffHere();
}

// Example 2
public void saveGame() throws Exception {
  doSamlStuffHere();
}

// Example 3
public class SaveException extends Exception {
  public SaveException(String msg, Throwable cause) {
    super(msg, cause);
  }
}

public void saveGame() throws SaveException {
  try {
    doSamlStuffHere();
  } catch (OpenSamlException e) {
    throw new SaveException("Saving game " + getSaveName() + " failed", e);
  }
}

示例 1 就是您现在所拥有的,它通过在方法的“可见”部分(这只是它的签名)中显式命名它来从概念上导出 OpenSaml 的想法。

示例 2 通过命名java.lang.Exception解决了这个问题。 它还剥夺了与抛出的问题进行有意义交互的能力( catch (Exception e)捕获了很多),所以它有点难看。 但它解决了问题。

示例 3 是“正确的”:它将 SAML 作为实现细节完全隐藏(没有任何公开可见的内容显示有关 SAML 的任何内容,就像示例 2 一样),但它确实让您可以专门与问题进行交互,将其重新抛出为异常还是具体的。 我在这里使用“保存游戏”作为示例。

示例 2 和 3 意味着您不再需要导出传递依赖项。

传递依赖确实需要在类路径上

在编译(和编写)代码时,导出的传递依赖项需要可用。 当然,当您运行代码时,该 dep 需要位于类路径中。

编译/编写时根本不需要存在非导出的传递依赖项。 但是很明显,当您运行代码时,它们仍然需要位于类路径中。 毕竟,您需要存在 SAML 才能运行saveGame()方法。 你不能希望它消失。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM