Java 9模块化:如何让module1的package1仅对module2的package2可见?
这个问题问得很有意思,刚好戳中了Java模块系统的一个粒度限制点——咱们先直接给结论:仅通过module-info.java的模块声明,没办法直接实现让package1只对module2里的package2可见,却对同模块的package3、4不可见。下面给你拆解原因和可行的替代方案:
为什么直接用module-info做不到?
Java模块系统的exports指令(包括限定导出exports ... to)的粒度是模块级别的,而非模块内的包级别。也就是说:
如果module1的module-info.java里写:
module module1 { exports package1 to module2; }
这代表把package1导出给整个module2模块,那么module2里的所有包(package2、3、4)只要属于module2,都能访问package1中的public类和接口。模块系统不会区分module2内部的各个包,只要归属目标模块,就有权访问导出的包。
可行的替代方案
如果一定要实现“package1仅对package2可见,对3、4不可见”的需求,有两种常用思路:
1. 拆分module2,把package2独立成新模块
把原来的module2拆成两个模块:
module2-core:仅包含package2module2-others:包含package3、package4,并且依赖module2-core
然后调整各模块的声明:
- module1的
module-info.java:module module1 { exports package1 to module2-core; } - module2-core的
module-info.java:module module2-core { requires module1; // 如果需要让module2-others访问package2的封装功能,可以导出package2给module2-others exports package2 to module2-others; } - module2-others的
module-info.java:module module2-others { requires module2-core; }
这样一来,package1只能被module2-core(也就是package2)访问,module2-others里的package3、4只能通过package2提供的封装接口访问,无法直接接触到package1。
2. 在module2内部做代码层面的封装
如果不想调整模块结构,保持module2包含三个包,那可以在代码层面做限制:
- 让package2作为访问package1的唯一入口:package2里的类直接调用package1的API,然后对外(给package3、4)提供封装后的方法或类
- package2中暴露给package3、4的类/方法,只暴露业务逻辑,不暴露package1的具体类型
- 同时,通过代码规范、静态检查工具(比如Checkstyle)约束package3、4的代码,禁止直接import package1的类
这种方式不是通过模块系统强制限制的,而是通过代码封装和规范来实现,但能达到需求中的访问控制效果。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

