The basic use of a modular system and the use of commands to compile and run our modules was introduced in the basic part of the previous article.

Let’s take a look at the module related keywords:



The exports/ Reuires/Module we are familiar with so far is also very simple to use. The following describes the application scenarios of other keywords.

System module

Since Java9, the JDK itself has been modularized, and if we use modularization, packages and objects that reference the system will need to include modules that depend on those packages in the module definition.



Among them, java.base is special. This module is automatically added by the compiler to our custom module dependency declarations. Let’s look at how this module is defined in the JDK source code:

C: / Program Files/Java/JDK – 10.0.1 / lib/SRC. Zip! /java.base/module-info.java

The module is deduced java.io/java.nio/java.lang/java.net/java.math/java.time/java.util core basic package, such as code so that we don’t need to show to import the package module depends on the statement.

Legacy code and anonymous modules

Since the Java9 module mechanism is arguably breaking change, he needs to address compatibility with older code. If we do not declare module-info.java in our code, our code is in a module called “unnamed Module”.

A “unnamed Module” has two desired characteristics. First, all packages in this module are automatically declared exports by default, so other external modules are readable to all their objects. Second, anonymous modules can access all other modules (with permission, of course).

When our code does not show the declaration module definition, the compiled code still uses the classpath mechanism instead of the mudule path mechanism mentioned above. It is these two default mechanisms that ensure that our projects can switch directly from Java8 and below to Java10. There is no need to adapt the new module mechanism.

So the DEVELOPERS of the JDK have put a lot of effort into this, and I have to give them a lot of credit.

Export to a specific module

Use the to keyword if you have objects in your module that are only allowed to be used by specific modules:

exportspackageName to moduleName1,moduleName1,... ;Copy the code

You can add multiple modules after to to modify the POJO module definition:

module pojo {
    exports pojo to order;
}Copy the code

When we compile the goods module, we get an error:

D:\code\mods>javac –module-path target -d target\goods goods\src\*.java goods\src\goods\*.java 

Goods \ SRC \goods\ goodsservice.java :5: error: package pojo not visible import pojo.goods; ^ (Package POJO was declared in module POJO, but the module did not export it to module goods) 1 error


Transitive

Goods -> Order -> POJO. Goods also depends on POJO. Let’s look at the current definition of the goods module:

module goods{
    requires order;
    requires pojo;
}Copy the code

Obviously the requires pojo; As in the order module, we just need to change the order module declaration:

module order {
    exports order;
    requires transitive pojo;
}
Copy the code

module goods{
    requires order;
}Copy the code

Module opening

open module

Packages in a module can only be accessed by other modules if they are declared exports in the module. Of course, it is important to understand that this refers to access during static compilation. Its definition is as follows:

open module moduleName{
    // Module definition
}Copy the code

For example, we added a package and class other.other to the POJO module. This is an empty class with nothing:

package other;

public class Other {} and thenCopy the code

Modify the POJO module definition by adding the open keyword:

open module pojo {
    exports pojo;
}Copy the code

We use the following in goods module:

GoodsService.java

package goods;


import order.OrderService;
import pojo.Goods;

public class GoodsService {

    private OrderService orderService = new OrderService();

    Goods queryGoodsInfoByName(String goodsName) {
        Goods goods = new Goods();
        goods.setGoodsName(goodsName);
        goods.setOrderList(orderService.queryOrdersByGoodsName(goodsName));
        return goods;
    }

    public static void main(String[] args) throws Exception{
        String module = "test".exports = "test",with="with";
        System.out.println(new GoodsService().queryGoodsInfoByName("test"));

        //test open module
        Object other = Class.forName("other.Other"); System.out.println(other); }}Copy the code

The above example uses reflection to create an instance of Other, and the program finds that it does. However, we did not define the POJO module:

exports other;

The visible open keyword makes poJO packages and objects open to other modules at run time, but not at compile time. Modify the sample code:

Other other = new Other();Copy the code

Compilation will not pass.

opens Statement

We want more fine-grained open package access by using a Labour of Love to open specific packages to external modules, providing runtime access. Its use is as follows:

opens packageName [to moduleName];Copy the code

2. The “open module” declaration cannot be used in open Modules because all packages in the module defined by open Module have the open attribute. 2. The commission only opens up access at run time, not compile time. 3, The commission can specify a specific module, and only the specified module can access the package at run time.

We can see that system modules also use this mechanism, such as java.desktp:

opens com.sun.java.swing.plaf.windows to jdk.jconsole;
opens javax.swing.plaf.basic to jdk.jconsole;Copy the code

requires static

With static, imported modules are only available at compile time and are not visible at run time. When you use this keyword, it must be clear that the imported module is optional at runtime, otherwise an error will be reported. For example, we change the definition of the goods module:

module goods{
    requires static order;
}Copy the code

Then compile, and everything is OK. But an error will be reported at runtime:

Exception in thread "main" java.lang.NoClassDefFoundError: order/OrderService
	at goods/goods.GoodsService.<init>(GoodsService.java:9)
	at goods/goods.GoodsService.main(GoodsService.java:20)
Caused by: java.lang.ClassNotFoundException: order.OrderService
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
	... 2 more

Process finished with exit code 1
Copy the code

conclusion

This is about the basic use of the module, we have learned:

  • How to define a module
  • System modules and anonymous modules
  • Module-dependent transitivity
  • How do I export a module to a target module
  • Open modules at runtime
  • Open packages under the specified module at runtime
  • Static module dependency