Java: Subpackage visibility? Java: Subpackage visibility? java java

Java: Subpackage visibility?


You can't. In Java there is no concept of a subpackage, so odp.proj and odp.proj.test are completely separate packages.


The names of your packages hint that the application here is for unit testing. The typical pattern used is to put the classes you wish to test and the unit test code in the same package (in your case odp.proj) but in different source trees. So you would put your classes in src/odp/proj and your test code in test/odp/proj.

Java does have the "package" access modifier which is the default access modifier when none is specified (ie. you don't specify public, private or protected). With the "package" access modifier, only classes in odp.proj will have access to the methods. But keep in mind that in Java, the access modifiers cannot be relied upon to enforce access rules because with reflection, any access is possible. Access modifiers are merely suggestive (unless a restrictive security manager is present).


Most of the answers here have stated that there is no such thing as a subpackage in Java, but that is not accurate. The term is defined in the Java Language Specification (JLS) and has been since the initial version of the specification.

Java 15 JLS:

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.

The subpackage concept has practical implications, as is enforces naming constraints between packages and classes/interfaces:

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.

However, this naming restriction 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.


With this context, we can answer the question itself. Since there is no special access relationship between a package and its subpackage, or between two different subpackages of a parent package, there is no way within the language to make a method visible to two different packages in the requested manner, while restricting its access from other packages. This is a documented, intentional design decision.

Either the method can be made public and all packages (including odp.proj and odp.proj.test) will be able to access the given methods, or the method could be made package private (the default visibility), and all the code that needs to directly access it must put in the same (sub)package as the method.

Regarding the test use case, a standard practice in Java is to put the test code for a type in the same package as its source code, but in a different location on the file system. For instance, in both the Maven and Gradle build tools, the convention would be to put the source files in src/main/java/odp/proj and the test files insrc/test/java/odp/proj. When compiled by the build tool, the items in both directories end up in the odp.proj package, but only the src files are included in the production artifact; the test files are only used at build time to verify the production files. With this setup, test code can freely access any package private or protected code of the code it's testing, as they will be in the same package.

In the case where you want code sharing across subpackages or sibling packages that isn't the test/production case, one solution I've seen some libraries use is to put that shared code as public, but document that it is intended for internal library use only.