javaencapsulationjlsjava-package

What do Java subpackages do, given that they don't provide a special access relationship?


I have seen a number of posts on Stack Overflow and elsewhere assert that Java does not have the concept of subpackages. One thing often pointed out is the lack of any special access relationship between a package and its "subpackage". For instance, there is no way to expose a class or method in com.example to classes in com.example.subpackage (or vice versa) without exposing it to all other packages. However, despite these assertions, I see that the Java Language Specification does in fact define the concept of "subpackage" in Chapter 7. Packages and Modules.

The members of a package are class and interface types, which are declared in compilation units of the package, and subpackages, which may contain compilation units and subpackages of their own.

What, therefore, is a subpackage in Java, and what does it do?


Solution

  • Subpackages exist to allow code to be conveniently organized. They impose a restriction on class/interface naming (a class cannot have the same fully qualified name as a subpackage), but are otherwise no different than two unrelated packages.

    The Java Language Specification defines what subpackages are in section 7.1, Package Members.

    A subpackage is any package directly nested within another package. For instance, com.example.subpackage is a subpackage of com.example:

    The members of a package are its subpackages and all the top level class types and top level interface types declared in all the compilation units of the package.

    For example, in the Java SE Platform API:

    • The package java has subpackages awt, applet, io, lang, net, and util, but no compilation units.
    • The package java.awt has a subpackage named image, as well as a number of compilation units containing declarations of class and interface types.

    Subpackages enforce naming constraints between subpackages and classes/interfaces within the package. Namely, a subpackage and a class/interface cannot share the same name within the same package:

    A package may not contain two members of the same name, or a compile-time error results.

    Here are some examples:

    • Because the package java.awt has a subpackage image, it cannot (and does not) contain a declaration of a class or interface type named image.
    • If there is a package named mouse and a member type Button in that package (which then might be referred to as mouse.Button), then there cannot be any package with the fully qualified name mouse.Button or mouse.Button.Click.
    • If com.nighthacks.java.jag is the fully qualified name of a type, then there cannot be any package whose fully qualified name is either com.nighthacks.java.jag or com.nighthacks.java.jag.scrabble.

    The subpackage concept primarly exists for organizational purposes. The restriction against name conflicts is the only significance afforded to subpackages by the language:

    The hierarchical naming structure for packages is intended to be convenient for organizing related packages in a conventional manner, but has no significance in itself other than the prohibition against a package having a subpackage with the same simple name as a top level type declared in that package.

    For example, there is no special access relationship between a package named oliver and another package named oliver.twist, or between packages named evelyn.wood and evelyn.waugh. That is, the code in a package named oliver.twist has no better access to the types declared within package oliver than code in any other package.