BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News JEP 476: Simplifying Java Development with Module Import

JEP 476: Simplifying Java Development with Module Import

After its review concluded, JEP 476, Module Import Declarations (Preview), was integrated into JDK 23. This preview feature proposes to enhance the Java programming language with the ability to succinctly import all of the packages exported by a module, with the goal of simplifying the reuse of modular libraries without requiring code to be in a module itself.

This JEP streamlines the importing of entire modules in Java, thus simplifying code and making it easier for developers, especially beginners, to utilize libraries and standard classes. This feature reduces the need for multiple import statements and eliminates the necessity of knowing the package hierarchy.

Importantly, this change does not disrupt existing code, as developers are not required to modularize their work. This feature is developed in conjunction with JEP 477, which automatically imports all public classes and interfaces from the java.base module for implicitly declared classes.

The Java programming language includes the automatic import of essential classes from the java.lang package.  However, as the platform has evolved, many classes, like List, Map, and Stream are not automatically included, forcing developers to import them explicitly.

For instance, the following code demonstrates how manually importing several packages consumes unnecessary lines:

import java.util.Map;                   
import java.util.function.Function;     
import java.util.stream.Collectors;     
import java.util.stream.Stream;

String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m =
    Stream.of(fruits)
          .collect(Collectors.toMap(s -> s.toUpperCase().substring(0,1),
                                    Function.identity()));

With module imports, the syntax simplifies significantly:

import module java.base;

String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m =
    Stream.of(fruits)
          .collect(Collectors.toMap(s -> s.toUpperCase().substring(0,1),
                                    Function.identity()));

A module import declaration follows this pattern:

import module M;

where M is the name of the module whose packages should be imported.

The effect of the import module is twofold:

  • Direct Packages: It imports all public top-level classes and interfaces in packages exported by the module M to the current module.
  • Transitive Dependencies: Packages exported by modules read via transitive dependencies are also imported.

As an example, the declaration import module java.base imports all 54 exported packages, effectively bringing a wide range of classes into scope from java.util to java.io.

However, importing entire modules increases the risk of ambiguous names when multiple packages contain classes with identical simple names. For instance, this example will trigger an error due to ambiguous List references:

import module java.base; // exports java.util.List

import module java.desktop; // exports java.awt.List

List l = ...                // Error - Ambiguous name!

The solution is to import the desired type explicitly:

import java.sql.Date; // resolve the ambiguity of the simple name Date!

Date d = ...                 // Ok! Date is resolved to java.sql.Date

The import module feature is currently a preview available through the --enable-preview flag with the JDK 23 compiler and runtime. To compile and run use the following command:

  • Compile the program with javac --release 23 --enable-preview Main.java and run it with java --enable-preview Main; or,

  • When using the source code launcher, run the program with java --enable-preview Main.java; or,

  • When using jshell, start it with jshell --enable-preview.

This JEP aims to provide a cleaner and more modular way to import Java libraries, reducing boilerplate code and enhancing accessibility, especially for new learners and developers working with modular libraries.

Overall, Java’s module import feature promises to improve productivity and ease of development. By simplifying imports, developers can focus more on crafting meaningful code and less on keeping their imports organized.

About the Author

Rate this Article

Adoption
Style

BT