Packages are an important part of the Java language, and they also
appear in other languages (although some languages call them
"namespaces"). You've been accessing some of Java's existing
packages whenever you use an import statement. For example, when you use the Scanner
class, you were using classes in another package. Classes like String
and Math are in the java.lang package, which is automatically
available to all programs without using import statements.
In this lesson, we'll learn why programmers use packages and why
they're important, and of course we'll also discuss the proper naming
conventions for packages in Java.
Programmers usually create their own packages (for reasons discussed in the
next section). For example,
in Logic class you worked with Dr. Becker's Robots. This collection of classes were organized into a
variety of
packages, such as becker.robots.
When you create your own packages, you are basically deciding how you will organize
your classes.
What Are Packages?
The simplest way to explain packages is that they are categories of classes
that also give us a way to uniquely identify classes that might have the
same name. This also defines the purpose of packages, but we'll talk
more about that in the next section Every class belongs to some kind of
package, even "no package at all" is technically a package: it's called the
default package. A package can contain
many classes, but generally all the classes in a package are related in some way:
usually they all share a similar purpose.
For example, there's a package in Java called java.io. The
java.io package contains classes for input and output.
For example, it contains a class called File that models or represents
any file or directory on the system (even if that file/directory doesn't exist),
and the PrintWriter class which is used to send formatted text to an
output source (like a file, or the monitor - in fact, PrintWriter owns the print() and
println() methods).
When you want to use a class in your code that is not part of the java.lang
package, you have to let Java know what package that class is in by doing one of
the following:
Import the class by using an import statement, e.g.
import java.io.File;.
Referring to the class by it's fully qualified name, e.g. java.io.File
Packages might also have "sub-packages". This might happen when there
are many classes and there needs to be more specific levels of
organisation. For example, the java.util package contains general
utility classes, such as those used for working with arrays and collections, and the
java.util.concurrent contain utility classes that are used in programs
that run multiple processes (threads) at once.
Note that if you use a wildcard import on a package, it only gives
access to that package's classes, not the sub-packages. For
example, if you import java.util.*; you will be able to
use the java.util.Arrays class but not the
java.util.concurrent.CopyOnWriteArrayList<E> class: you would have to also
import java.util.concurrent.*. But thankfully, we don't generally use wildcard
imports because they cause so many problems in larger programs!
Why Do We Need Packages?
Packages are used for a few very important reasons:
Class Organisation
There are thousands of classes in Java, and packages help organize all
of those classes into neat categories. This makes it easy to find classes.
Often you will create sets of classes that are related to each other,
and organizing them into one or more packages makes them more
organized, but also makes it easier to distribute your classes to
other programmers.
Class Identification
With the thousands and thousands of classes that people create, it's
inevitable that people will create classes with the exact same name.
In fact, there are already classes in Java that have the exact same
name, but they're in different packages.
For example, there are two classes in Java called Date:
one is in the java.util package and one is in the
java.sql package. When you're writing a program and you need
the Date class, Java will know which one you want because you'll either import
or specify the right package.
Class Protection
The access modifier protected on a data member or method
means that the member can only be accessed by classes in the same
package.
How to Create a Package
The first step to creating a package is choosing a name for your package.
It is likely that you'll be creating more than one package in your career,
so choose wisely! You also have to be careful not to choose a
name that someone else has chosen. For this reason, the standard convention
is to use your own domain name backwards. For example, my package name
would be com.terminallearning. I actually use wsj.terminallearning
because wsj are my initials and I figure my packages would be easier to find (there are a lot of
packages out there starting with com!).
The last part of your package name is more specific to what the package
contains. For example, I have the following packages that I use in my Java
programs:
wsj.terminallearning.gui - general stuff I've created to use with GUI
programs
wsj.terminallearning.gui.utils- various utility methods and
constants that I use for creating GUI applications
wsj.terminallearning.web - some networking methods and classes I created
for programming web applications
wsj.terminallearning.io - methods and classes I made to use with file I/O
wsj.terminallearning.db - lots of methods and classes I wrote to use with
database programs
Note that each portion of the package name is in lower-case letters and
separated by a colon. This is the standard convention for package names.
In fact, each portion of the package name that is separated by the periods
is actually part of a directory structure. For example, the java.util
package name means that there is a directory called java/ and it contains
a sub-directory called util/. Since we know there is also a package
java.util.concurrent, that means that util/ has a sub-directory called
concurrent/.
You'll find that when you start creating classes inside packages that
you'll see a similar directory structure.
My directory structure for my packages starts with wsj, which contains a
sub-directory terminallearning/.
The terminallearning/ directory contains the sub-directories gui, net,
io, and db, and so on...
Once you've decided on a name for your packages, you simply write the classes and methods that you want
your package to contain. Each of these classes and files must start with the
package statement.
The packagestatement must be the first statement in your file, above
the import statements (don't worry about comments/documentation).
In the package statement, the keyword package is
followed by the name of the package that this class will belong to. For example:
package wsj.terminallearning.db;
The statement above indicates that this class belongs to the wsj.terminallearning.db
package, and that the class's file can be found in the directory
wsj/terminallearning/db/.