Chapter:Classes - Packages
Meta information about this chapter (TODO)
Expand using link to the right to see the full content.
This chapter about classes deals with packages and the package declaration.
This lecture gives a basic introduction to the package declaration and how packages relate to the directory layout of source code and class files. We think it is natural to talk about packages early and frequently, since this is so central to Java software and APIs. It is so central, that we get back to the topic in a later chapter where we focus on using packages and the motivation for doing so.
The purpose of this chapter is to give a soft introduction and explain why source code files for Java classes almost always start with a package statement.
After this chapter, the student shall understand:
- The package statement and its relation to the directory layout (on a basic level)
- That packages are important and central and used everywhere
- That we will return to the topic in a later lecture
Instructions to the teacher
Don't make the mistake of skipping packages in your examples and exercises unless you point out the reason for doing so (brevity for instance). Make sure that the students understand paths (relative and absolute) because without that understanding, they will struggle to understand packages and how to compile and run programs using packages from the command line (but also IDEs might have settings for class path etc).
Paths are so important to understand, that we have a dedicated page about the topic.
Explain also to the students that we will get back to the topic of packages in a later lecture.
Full frontal - code up-front!
Here's what the package declaration can look like:
Introduction to the Package declaration
Imagine there are two classes with the same name and you want to use them both. Actually this is the case already in Java with a class called Date. In Java this is solved by adding an extra name to the class, we use the package construction. The two classes are
java.sql.Date and by using packages we can use them both.
Also imagine if you have a project with some thousand classes. Keeping all the corresponding Java files (the source code) in one directory would make it very hard to get an overview of the source code. Instead we split the project into smaller parts, each responsible for a part of the complete system. To achieve this we use the same construction as above.
We dare say that you will not see a program, in use by real users, that don't use packages. Not using packages is unfortunately something you will see in many books and education material. Since packages are easy to use we're going to use packages for everything we all write in the future - be it examples, exercises, assignments and exams.
A class can contain zero or one package declaration, which has to be the first statement in the source code file for the class. If the class source code doesn't have a package declaration, the class will implicitly belong to a "nameless" package, which could be thought of as "current directory". Packages correspond to the relative location of the compiled source code file. The source code is also saved in a directory structure matching the package name.
A class in the "nameless" package can only be found by the
java command (actually by the JVM's so called class loader) if the command is executed in the same directory as the class file (the compiled source code file). A class in an explicit package must be compiled into a directory matching the package name.
A package normally name consists of a series of lower case parts, separated by '.' (dots) leading up to the actual class name, as in
org.progund.Game, where Game is the name of the class. Each part leading up to the class name corresponds to physical directories of the same name and structure. If we look at
org.progund.Game again, the source code for Game.java should be located in a directory structure as shown below:
. `-- org `-- progund `-- Game.java
Note the dot at the top of the directory structure. This is the starting point of the relative path to Game.java. A dot signifies "current directory" in most terminals and shells. This is to say, that if we are in some directory and want to compile Game.java, and Game.java belongs to the package
org.progund, we need to make sure that the class file from compiling Game.java ends up in a directory structure according to the package name. Here, the first part of the package is
org. So we need to have a directory called "org". The next part is
progund, which means that inside "org" we need to have a directory "progund". This means that the dots correspond to the file separator character in a path! On UNIX-like systems (like cygwin), the file separator character is "/" (forward slash). So, the compiled file for
org.progund.Game must be located in the relative location
Now, if the source code file Game.java is in
org/progund/Game.java and we are in the current directory as shown above, if we compile the file using the relative path to it:
$ javac org/progund/Game.java
Then, the compiler (if the compilation is successful of course) will put the class file in the same directory as the source code. We will then have a directory structure as shown here:
. `-- org `-- progund |-- Game.class `-- Game.java
Now, let's pretend that the Game class has a main method, so that we can run it as a Java program. If we want to run it using the
java command, we will actually give
java the full class name (the qualified name including the package):
$ java org.progund.Game
We saw that the class file which is loaded and run by the JVM invoked by
java was located in the relative path
org/progund/Game.class but the argument to
org.progund.Game. This should make it obvious that the dots in the class name corresponds completely to the directory separators!
It is OK if you keep things as described above where the class files end up in the same directory as the source code files. But in the real world, it is actually common to keep two parallel file structures; one for the source code and one for the class files:
. |-- bin | `-- org | `-- progund | `-- Game.class `-- src `-- org `-- progund `-- Game.java
Now we've added to extra levels; the
bin directory, and the
src directory. Note that these are not part of the Java world! They are just there so that we can have two identical directory structures side by side!
If we'd want to run the program using Game.class, we'd have to
cd down to the
bin directory, so that
org.progund.Game still would translate to a valid relative path! If we
cd to the
bin directory, when the package name is translated to a relative path, the path would still be correct to the file
org/progund/Game.class. But if we'd stayed in the directory annotated as "." in the layout above (the directory where both bin and src are located), running
java org.progund.Game would yield a "Class not found" error from the
java command. This is only natural, because the JVM would translate the qualified name
org.progund.Game to a path for the class files
org/progund/Game.class. Trying to resolve that path would fail miserably, because there was no
org directory in the current directory! Only a
bin directory, and a
Now, there is actually a solution to this too! Java comes with a concept called "class path". If we were in the directory above
src, we could actually help
java find the
org.progund.Game class, by giving it a hint on where to look for the
$ javac -d bin src/org/progund/Game.java $ java -cp bin org.progund.Game Game over! $ ls bin src $ ls bin/org/progund/ Game.class $ ls src/org/progund/ Game.java
The trick was to provide the class path using the flag
-cp bin. That meant "run org.progund.Game but look in bin in order to find the class!".
Chapters about classes
Here are the chapters about classes in this book, so that you can keep a check on your progress:
- Chapter:Classes_-_Packages « you are here!
- Oracle's tutorial section on Classes
- Wikipedia on Java classes
- Oracle's tutorial section on Packages
- Wikipedia on Java packages
Where to go next
The next page has exercises for this chapter: Classes_-_Packages_-_Exercises