当前位置: 首页 > 面试题库 >

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

王才英
2023-03-14
问题内容

背景

在Maven中,工件可以使用

<optional>true</optional>

这意味着该依赖性不是必需的,但可以使用(如果存在)。

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

问题

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

用例

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

我想我们可以针对每种配置将其拆分为一个单独的模块,但这将导致JAR数量的爆炸性增长,因为我们不仅需要为每个可选依赖项单独使用一个JAR,而且对于大多数对还需要一个单独的JAR可选依赖项…


问题答案:

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

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

  • 在编译时,requires static M表示强制依赖。如果在可观察模块中找不到合适的模块并解决,这是一个错误。

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

因此,该形式的假设模块声明

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将它们包括在模块图中。



 类似资料:
  • 问题内容: 我有一个二进制文件,其中ldd显示了意外的依赖项和libicuuc(来自“ icu”)。 由于在该系统上libxml动态依赖于libicuuc,因此ldd最终会找到它是有意义的,但是是否期望libicuuc也出现在A的ldd输出中?是否有一些命令仅检索链接为依赖项依赖关系的库? 问题答案: 显示启动应用程序或加载共享库时需要加载的所有库。 仅显示二进制文件的直接依赖项。 是否有一些命令

  • 问题内容: 我在ivaven.xml中添加了一个依赖项(让我们将其命名为A),它在maven Central中具有一个pom文件。Ivy使用ibiblio解决了Maven依赖关系。添加到ivy.xml的依赖项(A)具有传递的依赖项(B)。到目前为止,到目前为止很好。常春藤无法解决传递性依赖项(B)的依赖项(C)。 我在ivy.xml中定义了A,如下所示: 在B的pom文件中,在编译和测试范围中都定

  • 编写的PHP扩展需要需要依赖另外一个扩展,在PHP-X中可以调用Extension->require来实现。 PHPX_EXTENSION() { Extension *ext = new Extension("test", "0.0.1"); ext->require("swoole"); ext->require("sockets"); return ext;

  • 依赖关系 这是一个非常轻量级的模块,没有其他依赖项。希望大家在JVM或Android上使用以太坊的RLP编码的项目时会选择使用这个模块,而不再编写自己的实现。

  • 依赖关系 ABI一个非常轻量级的模块,唯一的第三方依赖是 Bouncy Castle,用于hash加密 (Spongy Castle on Android)。 最后希望java和安卓开发者,在JVM或Android上有以太坊ABI合作的项目时会选择使用这个模块,而不是再编写自己的实现。

  • GCC编译器提供了一组内置函数来测试某些处理器特性,如某些指令集的可用性。但是,根据这个线程,我们也可能知道某些cpu功能可能不会被OS启用。所以问题是:<code>__builtin_cpu_supports</code>intrinsic是否也检查操作系统是否启用了某些处理器功能?