Split packages

Here's a question that some of you might be asking already. The LibApiImpl class is package-private. So, there's no way it is accessible to a type outside the packt.lib.external package it is in. So, our attempt to access the type in packt.app.App, a completely different package, was bound to fail anyway! In fact, it would have failed even in Java 8 or earlier! How about if we try to access it from the same package in another module? If we were to create the same package packt.lib.external in the app module and create a new class there, would that class be able to access LibApiImpl? In this scenario, the consuming class is in the same package. Let's give it a try! You don't have to go too far. Just creating the same package from one module into another module doesn't work. Let's say you recreate the package in the app module and add any arbitrary Java type in it:

    package packt.lib.external; 
    public class App { 
      public static void main(String[] args) { 
        System.out.println("Test"); 
      } 
    } 

We are not even using LibApiImpl here! We've just used the same package in another module. The compilation step will fail with the error:

$ javac --module-source-path src -d out $(find . -name '*.java') 
./src/app/packt/lib/external/App.java:1: error: package exists in another module: lib 
package packt.lib.external; 
^ 
1 error 

Yes! A package cannot exist in two modules at the same time. Well, not in two observable modules, at least! In other words, given a package in an application, it should be a part of one and only one module on the module path!

This is a significant deviation from how we've traditionally thought of libraries in Java. Having come this far, I don't have to highlight that modules are different from traditional JAR libraries. But here is yet another aspect that breaks the traditional library paradigm. Traditionally, multiple jars in the class path can contain the same package. We've seen this figure already in Chapter 1, Introducing Java 9 Modularity:

With modules not allowing sharing of packages, or split packages as they're often called, we now end up with a new hierarchy. Modules at the top, packages under them, and then types under packages, as shown in the following diagram with a couple of example modules:

This now results in another change to the way we think about packages. Packages are not grouping of types in the entire application anymore. Packages are grouping of types only inside a single module. When you create a package, you are forced to choose which module the types should all be in. One advantage of this approach, if we design our packages well, is clearer organization. There are also performance optimizations. The Java class loader internally maps each package to a single module, so when it's looking up types to load, it immediately knows where (and in which module) to find a given type.

This restriction of avoiding split packages will come back to be a bitter pain in the neck when migrating legacy Java codebases to Java 9 modules which we'll cover in Chapter 11, Migrating Your Code to Java 9. Also note that there are ways to bypass this restriction by using multiple class loaders, but that's beyond the scope of what we are covering here.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.249.174