Java 9 Module系统是否支持可选的依赖项?

背景

在maven中,工件可以声明依赖关系

true 

这意味着不需要依赖项,但如果存在则可以使用。

模块系统的状态似乎指定模块只能读取它所需的模块。

问题

  • Java 9模块系统确实不支持可选的依赖项吗?
  • 为什么不?
  • Java 9模块系统提供了哪些可选依赖项替代方案?

用例

我有一个框架,集成了应用程序可能使用或不使用的各种库。 目前,该框架是一个单独的JAR,它反映了类路径以跳过缺少库的集成代码。

我想我们可以将它分成每个配置的单独模块,但这会导致JAR数量的组合爆炸,因为我们不仅需要为每个可选依赖项单独的JAR,而且对于大多数对都需要单独的JAR可选依赖项…

是的, 支持可选的依赖项 。 引用原始提案 :

扩展模块声明的语言以允许在require指令上使用static修饰符,具有以下含义:

  • 在编译时, requires static M表示强制依赖。 如果在可观察模块中找不到合适的模块并进行解决,则会出错。

  • 在编译时间之后的阶段, requires static M表示可选的依赖性。 在解析期间,模块系统不会在可观察模块中搜索合适的模块,但如果生成的模块图包含合适的模块,那么它将在执行通常的解析后健全性检查之前添加适当的可读性边缘。 […]

因此,forms的假设模块声明

 module joda.beans { requires static joda.collect; ... } 

将确保joda.collect模块在编译时可用,以便joda.beans模块中引用joda.collect可以毫不joda.collect地编译。 但是,它不能保证joda.collect在链接时或运行时可用。

(与此同时, 为该function创建了官方文档 。)

我为此写了一个演示 。 有趣的花絮是模块的module-info.java ,声明可选的依赖…

 module org.codefx.demo.advent { // list the required modules requires org.codefx.demo.advent.calendar; // with 'static' the factories are only required at compile time; // to be present at run time either other modules most require them // or they must be added with the '--add-modules' command line option requires static org.codefx.demo.advent.factory.chocolate; requires static org.codefx.demo.advent.factory.quote; } 

…以及想要从其可选依赖项访问类型的同一模块中的代码。 它必须编写,以便如果不存在ChocolateFactory和/或QuoteFactory类型,它将失败:

 private static List createSurpriseFactories() { return Stream.of( createChocolateFactoryIfAccessible(), createQuoteFactoryIfAccessible()) .flatMap(Optional::stream) .collect(toList()); } private static Optional createChocolateFactoryIfAccessible() { try { return Optional.of(new ChocolateFactory()); } catch (NoClassDefFoundError er) { return Optional.empty(); } } private static Optional createQuoteFactoryIfAccessible() { try { return Optional.of(new QuoteFactory()); } catch (NoClassDefFoundError er) { return Optional.empty(); } } 

最后,命令行可用于定义应用程序启动的模块:

 $java \ --add-modules org.codefx.demo.advent.factory.chocolate,org.codefx.demo.advent.factory.quote \ -p mods -m org.codefx.demo.advent 

当然,其他模块也可以非可选地要求它们,这迫使JVM将它们包含在模块图中。