So far, we have identified two basic modifiers indicating the range within which a variable or function is accessible: public and private. As we have said already, public data is visible to all classes and private data is visible only within a class (but to all instances of the same class, so one object of a class can freely examine private variables of another object of the same class).
In all this, we have also frequently written definitions without modifiers, such as
class LinearList{ ... }
How visible are such definitions?
Java has a separate mechanism to group togther classes using packages. A package, roughly speaking, is a group of classes that are defined in the same directory. To indicate that the class XYZ defined in the file XYZ.java belongs to the package named ABC, we add the line package ABC as the first line in XYZ.java. There is a (somewhat arbitrary) restriction on package names: all files in package ABC must live in a directory called ABC.
If a file does not carry a package header, its contents implicitly belong the (unique) anonymous package. All files without a package header in the same directory belong to the same anonymous package.
Definitions without modifiers are visible within the same package. The class definition above is ``public'' within the package but ``private'' outside the package. So, in our toy programs, all definitions without modifiers behave like public definitions so long as the definitions lie within the same directory (and thus belong to the anonymous package).
Java packages are arranged in (multiple) directory trees. Java searches for classes using the variable CLASSPATH, similar to the PATH variable used by the Unix shell to search for executable files. Suppose CLASSPATH contains the directory /usr/local and under this, we have a class def that lies in the subdirectory /usr/local/java/xyz/abc. Then, the package name associated with def corresponds to the directory abc and is given by java.xyz.abc while the fully qualified class name of def is java.xyz.abc.def. This reflects the path to reach def relative to the CLASSPATH, with / replaced by ..
The builtin classes in java typically lie in packages of the form java.xyz.abc. To use classes defined in a package we can use an import statement at the top of the file. For instance, if we write
import java.math.BigDecimal
then the class BigDecimal defined under .../java/math becomes accessible in the current program. More generally, we write
import java.math.*
to make all classes defined in .../java/math accessible to the program. Note here that the * is not recursive, so it does not make available any classes that may lie in subdirectories of .../java/math.
If we do not use the import statement, we can always explicitly select a class by giving its fully qualified name (much like giving the full pathname of a Unix command) and write, for instance,
java.math.BigDecimal d = new java.math.BigDecimal();
instead of
import java.math.* BigDecimal d = new BigDecimal();
Packages are intended to correspond to natural units of software development so it makes sense for some definitions to be fully visible within the ``current project'' but not outside.