Image by b1-foto from Pixabay

Classes are the basic unit of a program in Java. Packages are used to manage classes and modules are used to manage packages.

Modules were introduced in Java 9. Before that, an application consists of packages that hold classes. It is a problem in large codebases. A public class means that anyone from anywhere could access that class, which can lead to unwanted dependencies. Modules are uniquely named, reusable groups of related packages as well as resources.

A Module controls which packages should be private for internal use only and which should be public for other modules to use. In modular Java, a public class no longer means that anyone can access that class from anywhere, instead, it is public within a module only, unless module exports its package for other modules to use. It will print out a list of Java modules.

From Java 9, the language itself has broken down into modules. Run java --list-modules on JDK 9 or above.

You can check any module’s meta-data with the command: java --describe-module [module name]. For example:

exports java.util.logging the classes in this package are accessible to other modules.
requires java.base mandated this module depends on another module named: mandated.
provides ... this module is providing a service implementation (we won't cover services in this article)
contains this is an internal package, accessible within module only.

A bare minimum Java module Example

Our sample application will contain two modules, one for utilities called utils and one main application module that will use the utils module. Let’s code it up:

Create a directory JavaModuleExample and cd into it:

Create root and subdirectories to contain code. Utils module will be in module.utils directory and App module will be in module.app directory. Both directories will contain their sub-packages. Let's create them:

Final Directory Structure would look like:

In the above structure, module.app has package com.module.app and module.utils has package com.module.utils.

Utils Module

Let’s complete module.utils. Create a new Java File Utils.java in package com.module.utils with the following cat command. It will start waiting for text input.

paste following code in the console, press Ctrl+D when finish

To tell Java we are writing a module, we need to provide module-info.java at the root level of the module. Create the following file again with cat command:

paste following code in console, press Ctrl+D when finish

In the above file, we are specifying our module, the name of the module is module.utils, you can name it whatever you want, but is a convention to name module the same way as we name packages.

The Other thing is we are exporting a package com.module.utils. We want this package to be available in other modules. If you don't explicitly export it, then by default, it will be only accessible within the module itself.

That’s it, we have created a simple module.

App Module

The Next step is to complete module.app. Again, we need module-info.java at root of our App module and since our app module has a dependency on the utils module, we need to specify that dependency in module-info.java. Create module-info.java with the following command:

paste following code in console, press Ctrl+D when finish

In the above file, we need to explicitly tell which modules do we need as a dependency. requires module.utils is specifying we need the utils module in our app module.

Now Create Main class to use Utils.

paste following code in console, press Ctrl+D when finish

we are calling sum(...) function from Utils class that exists in the util module.

Finally, our application would look like:

Compile

Run the following command to compile code:

javac is java compiler that will compile java code to byte code
-d outDir is where our compiled code will go
--module-source-path . we are specifying module source path, which is current directory .
$(find . -name "*.java") we are specifying which files to compile (all files ending with .java)

Run

Run the following command to run code:

java --module-path outDir will specify compiled modules directory
-m module.app/com.module.app.Main specifying which class to run, Main class in module.app

3 is printed as a result, which is the result of Utils.sum(1,2), the code we have written in our Main class in the App module.

That was a basic introduction to modules in Java. As a side note, I would like to mention that you should not confuse Java modules with maven modules or IntelliJ IDEA modules. Maven and IntelliJ IDEA have their concepts of modules too. Also, IntelliJ IDEA supports Java modules too, see this post here.

Originally published at https://thebackendguy.com on May 9, 2020.

Software engineer | Writer | Author of TheBackendGuy.com