是的,支持可选依赖项。引用原始提案:
扩展模块声明的语言以允许在指令static
上使用修饰符requires
,具有以下含义:
因此,形式的假设模块声明
module joda.beans {
requires static joda.collect;
...
}
将确保该joda.collect
模块在编译时可用,以便可以毫不费力地编译joda.beans
引用的模块中的代码。joda.collect
但是,它不能保证joda.collect
在链接时或运行时可用。
(与此同时,为该功能创建了官方文档。)
我为此写了一个演示。有趣的花絮是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<SurpriseFactory> createSurpriseFactories() {
return Stream.of(
createChocolateFactoryIfAccessible(),
createQuoteFactoryIfAccessible())
.flatMap(Optional::stream)
.collect(toList());
}
private static Optional<SurpriseFactory> createChocolateFactoryIfAccessible() {
try {
return Optional.of(new ChocolateFactory());
} catch (NoClassDefFoundError er) {
return Optional.empty();
}
}
private static Optional<SurpriseFactory> 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 将它们包含到模块图中。