JAVA PACKAGES
Contents
Overview
- Every class is part of some package.
- All classes in a file are part of the same package.
- You can specify the package using a package declaration:
as the first (non-comment) line in the file.
- Multiple files can specify the same package name.
- If no package is specified, the classes in the file go into a
special unnamed package (the same unnamed package for all files).
- If package name is specified, the file must be in a subdirectory
called name (i.e., the directory name must match the package
name).
- You can access public classes in another (named) package using:
You can access the public fields and methods of such classes using:
package-name.class-name.field-or-method-name
You can avoid having to include the package-name using:
or
import package-name.class-name;
at the beginning of the file (after the package declaration).
The former imports all of the classes in the package, and the second
imports just the named class. You must still use:
to access the classes in the packages, and
class-name.field-or-method-name
to access the fields and methods of the class; the only thing you can
leave off is the package name.
Examples
Assume that you are working in a directory called Javadir, and that you
create four files, whose contents are shown below.
file 1
package ListPkg;
public class List { ... }
class ListNode {...}
file 2
package ListPkg;
public class NoNextItemException { ... }
file 3
public class Test { ... }
class Utils { ... }
file 4
class Test2 { ... }
Here are the directories and file names you must use:
- File 1 must be in a subdirectory named ListPkg, in a file named
List.java.
- File 2 must also be in the ListPkg subdirectory, in a file named
NoNextItemException.java.
- File 3 must be in a file named Test.java (in the Javadir directory).
- File 4 can be in any .java file (in the Javadir directory).
And here are the classes that can be accessed by the code in each file:
- Files 1 and 2:
- The code in the first two files (ListPkg/List.java and
ListPkg/NoNextItemException.java) can access the classes
defined in the same package (List, ListNode, and NoNextItemException).
(No access was specified for those classes, so they get
the default, package access.)
- The code in files 1 and 2 cannot access class Test, even
though it is a public class. The problem is that Test is in an
unnamed package, so the code in the ListPkg package has no way to
import that package, or to name class Test.
- The code in files 1 and 2 cannot access classes Utils and
Test2, because they have default (package) access, and are in a
different package.
- Files 3 and 4:
- The code in file 3 (Test.java) can access classes ListPkg.List,
ListPkg.NoNextItemException, Test, Utils, and Test2 (the first two
because they are public classes in a named package, and the last
three because they are in the same, unnamed package, and have either
public or package access). Note however, that if the code in
Test.java uses the class Test2, and that class is not in a
file called Test2.java, then the file that contains class Test2
must be compiled first, or else the class will not be found.
- The code in file 4 (the file that contains class Test2) can access
the same classes as the code in file 3 (Test.java).
Here's a summary of the example:
File Contents Directory/FileName Can Access
| | |
package ListPkg;
public class List {...}
class ListNode {...}
| ListPkg/List.java | List, ListNode, NoNextItemException
|
package ListPkg;
public class NoNextItemException
{...}
| ListPkg/NoNextItemException.java | List, ListNode, NoNextItemException
|
public class Test {...}
class Utils {...}
| Test.java | ListPkg.List, ListPkg.NoNextItemException, Test, Utils, Test2
|
class Test2 {...}
| any-name.java | ListPkg.List, ListPkg.NoNextItemException, Test, Utils, Test2
|
How the Java Compiler Finds Files
When you compile a file that uses a class (or interface) that is not defined
in the same file, the Java compiler uses
- the name of the class
- the names of imported packages (if any)
- the name of the current package
to try to locate the class definition. For example, assume that you are
working in directory Javadir, which contains one file named Test.java:
import ListPkg.*;
public class Test {
List L;
...
}
Since List is not defined in Test.Java, and since there is no file
List.java in the current directory, the compiler will look for List.java
in the ListPkg subdirectory (since Test.java imports the ListPkg
package).
Now suppose that the ListPkg subdirectory contains two files: List.java
and ListNode.java, both part of the ListPkg package. Also
assume that List.java uses the ListNode class defined in ListNode.java.
If you try to compile just List.java in the ListPkg subdirectory, you
will get an error, because the compiler will try to find the file
ListNode.java in a "ListPkg" subdirectory of the current directory,
rather than looking in the current directory itself.
There are (at least) three ways to solve this problem:
- Always compile a package from the parent directory.
For example, compile List.java from Javadir, rather than from
Javadir/ListPkg; in the Javadir directory, type:
- Always compile all files in a package at the same time;
for example, in the directory Javadir/ListPkg type:
- Make a circular link from the package subdirectory to itself;
for example, in the directory Javadir/ListPkg type:
The CLASSPATH Environment Variable
To use a package that is not in a subdirectory of the current
directory (i.e., the directory in which you invoke javac), you must
set the environment variable CLASSPATH to tell the java compiler where
to look.
For example, if there were a List package in
/p/course/cs368-horwitz/public/ListPkg,
you would set CLASSPATH like this:
setenv CLASSPATH .:/p/course/cs368-horwitz/public
Including the dot and the colon before the directory tells the compiler
also to look in the directory in which the compile is being done.
Note that you should set the CLASSPATH variable to the parent
of the "ListPkg" subdirectory, not to the ListPkg subdirectory itself.