Appearance
Lesson 01 · Modules Basics
Objectives
After this lesson you will be able to:
- Declare a module with
module-info.java(requires,exports). - Explain strong encapsulation and readability.
- Tell the module path from the classpath.
module-info.java
A module is a named, self-describing set of packages. Its declaration lives in module-info.java at the module's source root:
java
module com.acme.app {
requires com.acme.util; // I depend on (read) this module
requires java.sql; // platform modules too
exports com.acme.app.api; // expose THIS package to others
}requires X— this module readsX; you can useX's exported types.exports P— packagePis accessible to other modules; packages not exported are strongly encapsulated (invisible even via reflection by default).
java
exports com.acme.app.internal to com.acme.tests; // qualified: only to named modulesExam trap
A module reads only what it requires — there is no transitive readability unless the dependency uses requires transitive (next lesson). A package is hidden unless **exports**ed, even if its types are public. java.base is implicitly required by every module — you never write requires java.base.
Strong encapsulation
Before modules, public meant "visible everywhere on the classpath." With modules, a public type in a non-exported package is invisible to other modules — encapsulation the compiler and runtime enforce. This is the headline benefit of JPMS.
Module path vs classpath
| Classpath | Module path | |
|---|---|---|
| Unit | JARs/dirs of classes | modules (with module-info) |
| Encapsulation | none (public is global) | enforced by exports |
| Flag | -cp / -classpath | --module-path / -p, run with -m |
bash
javac -d out --module-source-path src $(find src -name "*.java")
java --module-path out -m com.acme.app/com.acme.app.MainSDET note
Modules make "what's public API vs internal" explicit and enforced — useful when testing a library, since tests must requires the module and can only touch exported packages (or use a qualified exports … to / opens for white-box tests).
Key Takeaways
- A module is declared in
module-info.javawithrequires(what it reads) andexports(what it exposes).java.baseis implicit. - A non-exported package is strongly encapsulated even if its types are
public. - Readability is not transitive by default;
exports … todoes a qualified export to named modules only. - The module path (
--module-path/-p, run-m) enforces encapsulation; the classpath does not.
Lesson Quiz
Which directive exposes a package to other modules?
Do you need requires java.base; ?
A public class is in a package that is NOT exported. Can another module use it?
Module A requires B, and B requires C. Can A read C's exported types?
Next: Services & Migration. Run the matching code in labs/src/main/java/com/jse21/m10_jpms/.