PACKAGES
Many times our Java applications consist of few classes; thereby we keep all such
classes inside a single directory. However it will be more difficult if our applications grow
into several classes and files. In such cases, we are grouping them into many
categories according to their usability and functionality and keeping them into multiple
directories for effective taxonomy.
Java APIs are centred on packages. Some of the packages are already introduced such
as java.lang and java.io. Here, java is a package and lang is a subpackage within java
package.
Package name (e.g., java.util) and classname (e.g., Scanner) together form the so-
called fully-qualified name in the form
of packagename.classname (e.g., java.util.Scanner), which unambiguously identifies a
class.
Packages are used for:
1. Organizing classes and related entities.
2. Managing namespaces - Each package is a namespace.
3. Resolving naming conflicts. For example, com.zzz.Circle and com.yyy.Circle are
treated as two distinct classes. Although they share the same classname Circle,
they belong to two different packages: com.zzz and com.yyy. These two classes
can co-exist and can even be used in the same program via the fully-qualified
names.
4. Access control: Besides public and private, you can grant access of a
class/variable/method to classes within the same package only.
5. Distributing Java classes: All entities in a package can be combined and
compressed into a single file, known as JAR (Java Archive) file, for distribution.
Package Naming Convention
A package name is made up of the reverse of the domain Name (to ensure uniqueness)
plus your own organization's project name separated by dots. Package names are in
lowercase. For example, suppose that your Internet Domain Name is "zzz.com", you can
name your package as "com.zzz.project1.subproject2".
The prefix "java" and "javax" are reserved for the core Java packages and Java
extensions, e.g., java.lang, java.util, and java.net, javax.net.
Package Directory Structure
The "dots" in a package name correspond to the directory structure for storing the class
files. For example, the com.zzz.Cat is stored in directory "...\com\zzz\Cat.class"
and com.yyy.project1.subproject2.Orange is stored in directory
"...\com\yyy\project1\subproject2\Orange.class", where "..." denotes the base directory of
the package.
JVM can locate your class files only if the package base directory and the fully-qualified
name are given.
The "import" Statement
There are two ways to reference a class in your source codes:
1. Use the fully-qualified name in the form of packagename.classname (such
as java.util.Scanner). For example,
public class ScannerNoImport
{
public static void main(String[] args)
{
// Use fully-qualified name in "ALL" the references
java.util.Scanner in = new java.util.Scanner(System.in);
System.out.print("Enter a integer: ");
int number = in.nextInt();
System.out.println("You have entered: " + number);
}
}
Take note that you need to use the fully-qualified name for ALL the references to
the class. This is clumpy!
2. Add an "import fully-qualified-name" statement at the beginning of the source
file. You can then use the classname alone (without the package name) in your
source codes. For example,
import java.util.Scanner;
public class ScannerWithImport
{
public static void main(String[] args)
{
// Package name can be omitted for an imported class
// Java compiler searches the import statements for the fully-qualified
//name
Scanner in = new Scanner(System.in); // classname only
System.out.print("Enter a integer: ");
int number = in.nextInt();
System.out.println("You have entered: " + number);
}
}
The compiler, when encounter with a unresolved classname, will search
the import statements for the fully-qualified name.
The import statement provides us a convenient way for referencing classes without using
the fully-qualified name. "Import" does not load the class, which is carried out by the so-
called class loader at runtime. It merely resolves a classname to its fully-qualified name,
or brings the classname into the namespace. "Import" is strictly a compiled-time activity.
The Java compiler replaces the classnames with their fully-qualified names, and removes
all the import statements in the compiled bytecode. There is a slight compile-time cost but
no runtime cost.
The import statement(s) must be placed after the package statement but before the class
declaration. It takes the following syntax:
import packagename.classname;
import packagename.*
You can import a single class in an import statement by providing its fully-qualified name,
e.g.,
import java.util.Scanner; // import the class Scanner in package java.util
You can also import all the classes in a package using the wildcard *. The compiler will
search the entire package to resolve classes referenced in the program. E.g.,
import java.util.*; // import all classes in package java.util
Using wildcard may result in slightly fewer source lines. It has no impact on the resultant
bytecode. It is not recommended as it lacks clarity and it may lead to ambiguity if two
packages have classes of the same names.
The Java core language package java.lang is implicitly imported to every Java program.
Hence no explicit import statements are needed for classes inside the java.lang package,
such as System, String, Math, Integer and Object.
There is also no need for import statements for classes within the same package.
Creating a Package
package package-name;
To put a class as part of a package, include a package statement before the class
definition (as the first statement in your program). For example,
package com.zzz.test;
public class HelloPackage {
public static void main(String[] args) {
System.out.println("Hello from a package...");
}
You can create and use package in IDE (such as Eclipse/NetBeans) easily, as the IDE
takes care of the details. You can simply create a new package, and then create a new
class inside the package.
Two Classes of the Same Classname
Suppose that we have two Circle classes in two different packages, can we use both of
them in one program? Yes, however, you need to use fully-qualified name for both of
them. Alternatively, you may also import one of the classes, and use fully-qualified name
for the other. But you cannot import both, which triggers a compilation error.