Recall our discussion of module systems: a module system's fundamental purpose is to isolate pieces of a system from each other, and provide well-defined interfaces through which the isolated pieces can interact.
In Java, the module system has two levels:
...is as simple as using a package declaration at the top of a source file. When something is not labeled public, private, or protected, it has "package" visibility, and may not be accessed outside of its declared package.
// FILE 1 package whales.baleen; public class HumpbackWhale { public void spout() { ... } void dive() { // Package-visible method StealthyWhale b = new StealthyWhale(); b.encounter(this); } void greet() { ... } // Another package-visible method } class StealthyWhale { // A package-visible class void encounter(HumpbackWhale hw) { System.out.println("Stealthy whale encounters humpback"); hw.spout(); hw.greet(); } } // FILE 2 package whales; // "import" is analogous to ML's "open ModuleName" declaration. It allows // you to refer to names in another package, without using the fully // qualified name. You can also import classes one at a time. import whales.baleen.*; public class KillerWhale { // This method's signature is illegal, because StealthyWhale has // package visibility to whales.baleen. public void eat(StealthyWhale sw) { System.out.println("Drat! Foiled!"); } // This method's signature is legal, but its implementation... public void eat(HumpbackWhale hw) { // ... calls the package-visibility method greet(), which is illegal. hw.greet(); System.out.println("Drat! Foiled again!"); } }