Java 9 中是否可以实现循环模块依赖?

Will Cyclic Module Dependencies be Possible in Java 9?

在Java 9、是否允许循环模块?如果没有,原因是什么?

module com.foo.bar {
    requires com.foo.baz;
    exports com.foo.bar.fizz;
}

module com.foo.baz {
    requires com.foo.bar;
    exports com.foo.baz.buzz;
}

没有。

文档

有趣的是 State of the Module System nor the Jigsaw Quick Start Guide address this issue. One source (found by ) is a JavaOne talk by Alex Buckley (see him explain it here). A more recent one is the list of open issues, which explicitly mentions cyclic dependencies:

The current draft disallows cycles when the module graph is initially resolved at compile time, link time, and run time. Cycles can arise later on at run time if readability edges are added for automatic modules, or via reflection. [...] This constraint is not, however, a documented requirement [...].

理由

循环依赖是不好的,mkay。 ;)

当两个实体(方法、类、模块、项目...)协作但没有充分解耦时,它们就会出现。对于用户和维护者来说,这种耦合意味着他们不能在不考虑另一个的情况下使用或改进一个。但这正是模块化试图实现的好处。

来自上面链接的问题列表:

The rationale for disallowing cycles during resolution is that it makes the module graph easier to reason about, it simplifies the module system itself, and that, philosophically, any modules involved in a cycle are logically one module anyway, so they should be defined as such in the first place.

实验

我创建了一些 demo project on GitHub that contains two cycles (pair: two -> one -> two; triple: three -> two -> one -> three). Trying the multi-module compilation 如快速入门指南所示,这些是结果:

./compile.sh
 > creating clean directories
 > compiling and packaging cycle "pair"
src/org.codefx.demo.cyclic.pair.one/module-info.java:2: error: cyclic dependence involving org.codefx.demo.cyclic.pair.two
        requires org.codefx.demo.cyclic.pair.two;
                                            ^
1 error
 > compiling and packaging cycle "triple"
src/org.codefx.demo.cyclic.triple.three/module-info.java:2: error: cyclic dependence involving org.codefx.demo.cyclic.triple.two
        requires org.codefx.demo.cyclic.triple.two;
                                              ^
1 error

所以你甚至不能编译模块,更不用说在配置中使用它们了。

除了模块是自动模块,不会出现这个问题。 只允许传递依赖关系并且传递依赖关系永远不会循环。