And*_*sha 5 java java-9 java-module module-info
我有一个这样的项目:
\---main
\---src
\---com.foo
\---UnnamedStart.java
\---api
\---src
\---com.foo.api
\---ApiInterface.java
\---module-info.java
\---impl
\---src
\---com.foo.impl
\---ApiInterfaceImpl.java
\---module-info.java
Run Code Online (Sandbox Code Playgroud)
的实现UnnamedStart.java是:
public static void main(String[] args) {
ServiceLoader<ApiInterface> services = ServiceLoader.load(ApiInterface.class);
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,main是未命名的模块。
api/src/module-info.java 是:
module com.foo.api {
exports com.foo.api;
}
Run Code Online (Sandbox Code Playgroud)
并且impl/src/module-info.java是:
更新 1.1 - 下面的代码更新见评论,添加requires
更新 1.2 - 下面的代码已更新,在创建问题时provides A with B更改为provides B with A错误,原本没问题
module com.foo.impl {
requires com.foo.api; //added (update 1.1)
provides com.foo.impl.ApiInterface
with com.foo.api.ApiInterfaceImpl; //vice versa (update 1.2)
}
Run Code Online (Sandbox Code Playgroud)
当我运行我的代码时,UnnamedStart.java我最终在services.
我还尝试在以下位置创建静态方法com.foo.api.ApiInterface:
static List<ApiInterface> getInstances() {
ServiceLoader<ApiInterface> services = ServiceLoader.load(ApiInterface.class);
List<ApiInterface> list = new ArrayList<>();
services.iterator().forEachRemaining(list::add);
return list;
}
Run Code Online (Sandbox Code Playgroud)
并api/src/module-info.java在行中添加uses com.foo.api.ApiInterface;但它给出了相同的结果(没有)。
我让它工作的唯一方法是将main从未命名模块迁移到命名模块。
1.当未命名模块试图与命名模块交互时,java 9如何工作?
2. 是否有可能让它工作并保持主要的未命名模块?
更新 1.3 -添加相关项目
ServiceLoader::load照常工作,但还有其他事情。
[简短回答]
1. 未命名模块对命名模块的读取与命名模块相同,但命名模块无法访问未命名模块中的类型。
2.您正在尝试从非模块化 JAR 启动应用程序,因此您必须通过 显式解析所需的模块--add-modules com.foo.impl。
请注意,您所需的模块必须位于模块图上(例如 add by --module-path)。
[更多细节]
1.有4种不同类型的模块:内置平台模块、命名模块、自动模块、 未命名模块,每种模块的命名与未命名模块不同
正如他们所写,未命名模块将所有其他模块视为与命名模块相同:
当然,所有其他模块都有名称,因此我们今后将这些模块称为命名模块。
未命名的模块读取所有其他模块。[...]
未命名的模块导出其所有包。[...] 但是,这并不意味着命名模块中的代码可以访问未命名模块中的类型。事实上,命名模块甚至不能声明对未命名模块的依赖。[...]
如果在命名模块和未命名模块中都定义了包,则未命名模块中的包将被忽略。
即使是自动模块也确实被命名为:
自动模块是隐式定义的命名模块,因为它没有模块声明。
2. 本答案的第二部分
如果您编译非模块化代码或从非模块化 JAR 启动应用程序,则模块系统仍在发挥作用,并且由于非模块化代码不表达任何依赖项,因此它不会从模块路径解析模块。
因此,如果非模块化代码依赖于模块路径上的工件,则需要使用选项手动添加它们
--add-modules。不一定是全部,只是那些你直接依赖的(模块系统将引入传递依赖) - 或者你可以使用ALL-MODULE-PATH(检查链接的帖子,它更详细地解释了这一点)。
这个@nullpointer 注释将会很有用
此外,模块解析仍然需要在启动期间解析 impl。要检查哪个,您还可以使用该
--show-module-resolution标志。
| 归档时间: |
|
| 查看次数: |
7076 次 |
| 最近记录: |