- Packaging Java Code
- Using Packaged Java Libraries
Packaging protects against name collisions.
- With thousands of Java libraries available, it’s inevitable that class and interface names will be duplicated.
- Packages allow you to use two different classes or interfaces with the same name.
Packages hide implementation that spans multiple classes (multi-class encapsulation).
- A set of classes might need access to each other, but still be hidden from the outside world.
-
Java packages support access levels other than
public
andprivate
to support information sharing and class visibility.
Packages help organize source code.
- Having all source files in the same directory becomes hard to manage as the projects grow.
- Packages allow you to group together related classes and interfaces into common directories.
![]() | Note |
---|---|
In addition to classes and interfaces, a Java package can contain definitions of enumerations and annotations. These Java constructs are discussed later in this class. |
A Java package name consists of a set of name components separated by periods (
.
).- Each name component must be a valid Java identifier.
A component name must not start with an upper-case letter.
Tip Best practice is for each name component to be all lower-case.
The package name corresponds to a directory structure on disk where the classes are stored.
-
For example, the class and interface files for
org.xml.sax
are located in the directoryorg/xml/sax
, relative to the directory where Java looks for classes (we’ll discuss this later in this module).
-
For example, the class and interface files for
To add a class or interface to a package:
-
Add
package
myPackageName
;
as the first Java statement of the source file - In your development directory, store the source file in a directory structure corresponding to your package name.
-
Add
![]() | Tip |
---|---|
Java does not require you to store your It’s also common to have separate, parallel directory hierarchies for your Most modern IDEs can create and manage your source and class file directory hierarchies automatically for you. |
![]() | Caution |
---|---|
If you don’t explicitly specify a package, your classes and interfaces end up in an unnamed packaged, also known as the default package. Best practice is not to use the default package for any production code. |
You can construct hierarchical package names, for example
org.xml.sax
andorg.xml.sax.helpers
.-
However, Java treats these as two independent packages, one with class files in
org/xml/sax
and the other with class files inorg/xml/helpers
. - The “information sharing” features of Java packages do not apply across these independent packages.
- Still, hierarchical package names are useful for grouping together related sets of classes.
-
However, Java treats these as two independent packages, one with class files in
To prevent package name collisions, the convention is for organizations to use their reversed Internet domain names to begin their package names.
-
For example,
com.marakana
-
If the Internet domain name contains an invalid character, such as a hyphen, the convention is to replace the invalid character with an underscore. For example,
com.avia_training
- If a domain name component starts with a digit or consists of a reserved Java keyword, the convention is to add an underscore to the component name.
-
For example,
Organizations often create sub-packages to reflect business units, product lines, etc.
-
For example,
com.marakana.android
-
For example,
-
Package names starting with
java.
andjavax.
are reserved for Java libraries.
Java does not do any explicit protection of package namespaces. This means that it is possible for an organization ABC to create a class in package com.xyz
even though the domain xyz.com
belongs to an organization called XYZ. However in practice organizations do not abuse each other’s namespaces.
The fully-qualified name for a class or interface is the package name followed by the class/interface name, separated by a period (
.
).-
For example,
com.marakana.utils.MyClass
-
For example,
- Code outside the package can reference public classes and interfaces of a package using their fully-qualified names.
- Code within the package can reference classes and interfaces of the package by their simple names, without package qualification.
To execute a Java application whose class is contained within a package, you must use its fully-qualified name.
For example, to run
ShapeDemo.main()
in the packageshape
you must invoke it as:java shape.ShapeDemo
Instead of using fully-qualified names for classes and interfaces, you can import the package member.
To import a specific member from a package, include an
import
statement specifying the fully-qualified name of that member. For example:import com.marakana.utils.MyClass;
You can then use the simple (unqualified) name of the member throughout the rest of the source file.
You can import all of the members of a package by importing the package with an asterisk (
*
) wildcard. For example:import com.marakana.utils.*;
You can then use the simple (unqualified) name of all the package members throughout the rest of the source file.
Important Using the wildcard
import
does not import any sub-packages or their members.
-
The
import
statements must appear after anypackage
statement and before all class/interface definitions in your file.
![]() | Note |
---|---|
The |
In case there are two or more classes with the same name but defined in different imported (or assumed) packages, then those classes must be referenced by their fully-qualified-class-name (FQCN).
For example, you could define:
com.mycompany.calc.AdditionOperation,
but someone else could implement:
com.othercompany.calculator.AdditionOperation.
If you wanted to use both addition operations from a class defined in com.mycompany.calc
package, then doing
import com.othercompany.calculator.AdditionOperation;
would make AdditionOperation ambiguous. Instead of importing it, you would reference it by its FQCN.
![]() | Caution |
---|---|
Even though importing an entire package using the asterisk ( |
Prior to Java 5, you always had to access static fields and methods qualified by their class name.
For example:
double c= Math.PI * Math.pow(r, 2.0);
Java 5 introduced
import static
to import static fields and methods.For example:
import static java.lang.Math.PI; // A single field import static java.lang.Math.*; // All static fields and methods
Once imported, you can use them as if they were defined locally:
double c= PI * pow(r, 2.0);
The the last module introduced the concept of the
public
andprivate
access modifiers that control access to fields, methods, constructors, classes, and interfaces.- There are two additional access levels:
Access Modifier | Description |
---|---|
| Accessible from any class |
| Accessible from all classes in the same package or any child classes regardless of the package |
default (no modifier) | Accessible only from the classes in the same package (also known as friendly) |
| Accessible only from within the same class (or any nested classes) |
- The class path is the path that the Java runtime environment searches for classes and other resource files.
-
By default, Java looks for classes in only the present working directory (
.
). To access classes at runtime outside the present working directory, there are three options:
-
Set an environmental variable named
CLASSPATH
with a colon-separated list of class directories, JAR files, and/or Zip files. (This should be a semicolon-separated list on Windows.) -
Use use the
-classpath
option (-cp
is an alias) withjava
andjavac
to override the class path with a colon/semicolon-separated list of class directories, JAR files, and/or Zip files. -
Copy classes to
$JAVA_HOME/lib/ext/
(this is typically used only for Java extensions).
-
Set an environmental variable named
![]() | Important |
---|---|
The class path should include only the root directory of a package directory hierarchy, not the individual package directories. |
For example, to run calc.CalculatorDemo
located in /home/me/classes/calc/CalculatorDemo.class
, you could do:
cd /home/me/classes java calc.CalculatorDemo
or (from any directory):
export CLASSPATH=/home/me/classes java calc.CalculatorDemo
or (from any directory):
java -classpath /home/me/classes calc.CalculatorDemo
or (from any directory):
cp -r /home/me/classes/calc $JAVA_HOME/lib/ext/. java calc.CalculatorDemo
It is important to notice the distinction between class path locations and package directories. Package-based directories should never be included within the class path and vice-versa.
This means that these would not work:
java -classpath /home/me/classes/calc CalculatorDemo java -classpath /home/me classes.calc.CalculatorDemo
A Java Archive (JAR) file packages multiple classes in a single compressed file.
- Based on the ZIP file format
- Easier and more efficient management of binaries
- Also known as Java library (.jar extension)
- Must preserve package directory structure
A JAR file can include additional meta-data in a manifest file at the pathname
META-INF/MANIFEST.MF
.-
The manifest is a text file containing
name: value
formatted entries. For example, you can make an executable JAR by including a
Main-Class
entry whose value is the fully-qualified name of a class containing amain()
method. You could then execute the JAR as:java -jar <file>.jar
-
The manifest is a text file containing
JAR files internally must look like package directories. For example, a class com.myco.calc.CalculatorDemo
would be stored within calculator.jar
file just like it would be stored on disk: com/myco/calc/CalculatorDemo.class
.
JAR files are referenced in the CLASSPATH
by their actual name, not by the name of the directory in which they are contained.
To run com.myco.calc.CalculatorDemo
you would do:
java -classpath calculator.jar com.myco.calc.CalculatorDemo
To make calculator.jar
executable:
-
Create a file:
META-INF/MANIFEST.MF
Add a line:
Main-Class: com.myco.calc.CalculatorDemo
-
Include
META-INF/MANIFEST.MF
incalculator.jar
Run with
java -jar calculator.jar
Create a JAR file
cd classes; jar -cvf shape.jar shape jar -cvf shape.jar -C classes shape
View the contents of a JAR file
jar -tvf shape.jar
Extract the contents of JAR file
jar -xvf shape.jar jar -xvf shape.jar META-INF/MANIFEST.MF
Update the JAR file (e.g., add to the manifest)
jar -uvmf MainClass.txt shape.jar
You will find that the jar
command has a usage similar to the Unix tar
command:
Usage: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ... Options: -c create new archive -t list table of contents for archive -x extract named (or all) files from archive -u update existing archive -v generate verbose output on standard output -f specify archive file name -m include manifest information from specified manifest file -e specify application entry point for stand-alone application bundled into an executable jar file -0 store only; use no ZIP compression -M do not create a manifest file for the entries -i generate index information for the specified jar files -C change to the specified directory and include the following file If any file is a directory then it is processed recursively. The manifest file name, the archive file name and the entry point name are specified in the same order as the 'm', 'f' and 'e' flags. Example 1: to archive two class files into an archive called classes.jar: jar cvf classes.jar Foo.class Bar.class Example 2: use an existing manifest file 'mymanifest' and archive all the files in the foo/ directory into 'classes.jar': jar cvfm classes.jar mymanifest -C foo/ .
![]() | Note |
---|---|
You can use any utility with support for ZIP files (e.g. WinZip) to create, view, extract, and manage your JAR files. |