Java 模块系统基础

笔记/Java/Java基础/Java高级核心/Java 模块系统基础

背景与动机#

当项目越来越大时,仅靠 package 已经不一定够用了。我们还会关心:

  • 这个子系统依赖谁
  • 哪些包允许暴露给外部
  • 哪些内部实现不应该被随便访问

Java 9 引入的模块系统(JPMS,Java Platform Module System)就是为了解决这类问题。

核心原理拆解#

1. 模块比包更高一层#

可以先这样理解:

  • package:组织类
  • module:组织包和依赖关系

也就是说,包解决“类怎么分目录”,模块解决“这一组包整体怎么对外暴露、怎么依赖别的模块”。

2. 模块的入口文件是 module-info.java#

一个最简单的模块声明长这样:

module com.example.app {
}

这个文件通常放在模块源码根目录下,用来声明模块名和模块规则。

3. requires:声明依赖哪些模块#

module com.example.app {
requires java.sql;
}

这表示当前模块依赖 java.sql 模块。

可以把它理解成:模块级别的“我需要用谁”。

4. exports:声明哪些包允许被外部访问#

module com.example.app {
exports com.example.service;
}

这表示外部模块可以访问 com.example.service 包中的公开类型。

如果某个包没有被 exports,即使里面有 public 类,其他模块也不一定能直接访问。

5. 模块边界和访问修饰符不是一回事#

这里很容易和上一节《包、作用域与访问控制》混在一起。

  • publicprivateprotected、默认权限:解决类或成员在代码层面的可见性
  • exports:解决整个包是否对其他模块开放

所以一个类即使是 public,如果它所在的包没有被模块 exports,别的模块仍然不一定能直接使用它。

6. packagemodule 的区别#

这两个很容易混:

  • package 是代码组织单位
  • module 是部署和依赖组织单位

简单说:

  • 类属于包
  • 包属于模块

7. 模块系统最核心的价值#

它主要带来三类好处:

  • 依赖关系更明确
  • 对外暴露面更可控
  • 大型项目边界更清晰

不过对初学者来说,不必把模块系统当成日常写小程序的必备知识。它在大型项目、框架、平台化工程里更有价值。

最小可运行结构示例#

src
├─ module-info.java
└─ com
└─ example
└─ service
└─ UserService.java

module-info.java

module com.example.app {
exports com.example.service;
}

UserService.java

package com.example.service;
public class UserService {
public void hello() {
System.out.println("hello");
}
}

这个示例展示了最基本的模块结构:模块名、包名、导出包。

常见陷阱与错误示例#

1. 误以为 public 类天然对所有模块都可见#

在模块系统里,public 还不够;如果所在包没有被 exports,外部模块依然可能访问不到。

2. 把模块和包当成同一个概念#

包是类的分组方式,模块是包和依赖关系的分组方式,层级不同。

3. 小项目一开始就过度模块化#

模块系统很有价值,但并不是所有小型练习项目都需要马上引入。先理解概念,再按实际规模决定是否使用更稳妥。

面试高频问题#

1. 什么是 JPMS#

JPMS 是 Java Platform Module System,也就是 Java 的模块系统,用来在包之上进一步管理依赖和暴露边界。

2. requiresexports 分别做什么#

requires 用来声明依赖哪些模块,exports 用来声明哪些包对外可见。

3. 模块和包有什么区别#

包组织类,模块组织包和依赖。包是代码层面的分组,模块是更高层级的边界控制单位。

4. public 类是不是天然能被别的模块访问#

不一定。除了类本身是 public,它所在的包通常还需要被 exports 出去。

一句话总结#

模块系统不是用来替代包的,而是在包之上再加一层“依赖声明和暴露控制”,更适合中大型 Java 工程。

文章目录

文章目录