Module import declarations in Java
Java 25 import module java.base;.
Import a whole module
**import module M; imports every public top-level type from all packages that M exports, plus those of modules M requires transitively. Previewed in Java 23 and 24, it became final in Java 25**.
import module java.base;
void main() {
var files = List.of(Path.of("a.txt"));
System.out.println(files);
}Compact files get it free
Why can a compact source file (just void main()) use List and Map with no import at all? It **implicitly imports module java.base**. In a normal class you write imports yourself, or import module java.base;.
Too many Lists
java.desktop exports java.awt.List. What happens in this compact source file?
import module java.desktop;
void main() {
List<String> xs = List.of("a");
System.out.println(xs);
}Prints [a]Compile errorThrows ClassCastException
Show the answer
Two imported modules export a type named List: java.util.List (from the implicit java.base) and java.awt.List. The simple name is ambiguous, so javac refuses.
Single-type imports win
A single-type import shadows module imports and on-demand imports. One extra line settles any clash.
import module java.desktop;
import java.util.List; // List = java.util.ListUsing java.sql.Date
import module java.sql;
Date d = new Date(0);java.base brings java.util.Date too: compile error.
import module java.sql;
import java.sql.Date;
Date d = new Date(0);The single-type import wins over module imports.
Encapsulation still applies
import module java.base; does not import internal packages like jdk.internal.misc. Module imports respect encapsulation: only exported packages come in.
Where it shines
Module imports are great for scripts, demos, teaching and quick tools: one line instead of a dozen. In big codebases, many teams still prefer explicit single-type imports, which document exactly where each type comes from.
Key takeaways
- Final in Java 25
- Imports only exported packages of the module
- Compact source files import java.base automatically
- Single-type imports resolve name clashes
import module java.sql; also gives you java.util.logging types, because java.sql requires java.logging transitively.
Practice questions
This compact source file imports java.sql. What happens?
import module java.sql;
void main() {
Date d = new Date(0);
System.out.println(d.getTime());
}- 1970-01-01
- 0
- Compile error
- Throws ClassCastException
Check your answer
Compile error. java.sql exports java.sql.Date and the implicit java.base import brings in java.util.Date, so the simple name Date is ambiguous.
You want to keep `import module java.sql;` and use java.sql.Date in the code above. Best fix?
- Write `import module java.sql.Date;`
- Rename the variable d
- Remove java.base from the JDK
- Add `import java.sql.Date;`, since a single-type import wins over module imports
Check your answer
Add `import java.sql.Date;`, since a single-type import wins over module imports. Single-type imports shadow on-demand and module imports, so Date now unambiguously means java.sql.Date.