Java Packages
To better organize classes, Java provides a package mechanism to distinguish class names in different namespaces.
Functions of Packages
- Organize classes or interfaces that are similar or related in the same package, making it easier to find and use these classes.
- Similar to folders, packages use a tree-like directory structure for storage. Class names within the same package are unique, while class names in different packages can be the same. When using classes with the same name from different packages, the package name should be included for distinction. Therefore, packages can prevent name conflicts.
- Packages also limit access permissions, allowing only classes with package access to access classes within a specific package.
Java uses the package mechanism to prevent naming conflicts, control access, and facilitate the search and location of classes, interfaces, enumerations, and annotations.
The syntax for a package statement is:
package pkg1[.pkg2[.pkg3...]];
For example, for a file named Something.java
with the content:
package net.java.util;
public class Something {
...
}
Its path should be saved as net/java/util/Something.java. The purpose of a package is to categorize different Java programs and make them more accessible for use by other Java programs.
A package can be defined as a group of related types (classes, interfaces, enumerations, and annotations) that provide access protection and namespace management for these types.
Here are some packages in Java:
- java.lang - Contains basic classes
- java.io - Includes functions for input and output
Developers can package a set of classes, interfaces, etc., into their own packages. This practice is encouraged in actual development. When you implement classes, grouping related classes makes it easier for other programmers to determine which classes, interfaces, enumerations, and annotations are related.
Since packages create new namespaces, there will be no naming conflicts with any names in other packages. Using the package mechanism makes access control easier and simplifies the location of related classes.
Creating Packages
When creating a package, you need to give it an appropriate name. If a source file includes classes, interfaces, enumerations, or annotation types provided by this package, the package declaration must be at the beginning of the source file.
The package declaration should be the first line in the source file, and each source file can only have one package declaration, which applies to all types in the file.
If a source file does not use a package declaration, its classes, functions, enumerations, annotations, etc., will be placed in an unnamed package.
Example
Let's look at an example where a package named animals
is created. It is common to use lowercase letters to avoid conflicts with class and interface names.
Add an interface to the animals
package:
/* File name: Animal.java */
package animals;
interface Animal {
public void eat();
public void travel();
}
Next, add an implementation of this interface in the same package:
package animals;
/* File name: MammalInt.java */
public class MammalInt implements Animal {
public void eat() {
System.out.println("Mammal eats");
}
public void travel() {
System.out.println("Mammal travels");
}
public int noOfLegs() {
return 0;
}
public static void main(String args[]) {
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
Then, compile these two files and place them in a subdirectory called animals
. Run them using the following commands:
$ mkdir animals
$ cp Animal.class MammalInt.class animals
$ java animals/MammalInt
Mammal eats
Mammal travels
The import Keyword
To use members of a package in a Java program, you need to explicitly import the package. This is done using the "import" statement.
In a Java source file, the import statement should follow the package statement and precede all class definitions. There can be none, one, or multiple import statements, with the syntax:
import package1[.package2...].(classname|*);
import package1[.package2…].(classname|*);
If a class within a package wants to use another class in the same package, the package name can be omitted.
Example
The following payroll package already contains the Employee class, and now we are adding a Boss class to the payroll package. The Boss class can reference the Employee class without using the payroll prefix. The Boss class instance is as follows.
Boss.java file code:
package payroll;
public class Boss {
public void payEmployee(Employee e) {
e.mailCheck();
}
}
What if the Boss class is not in the payroll package? The Boss class must use one of the following methods to reference a class in another package.
Using the full class name, for example:
payroll.Employee
Using the import keyword with the wildcard *
:
import payroll.*;
Using the import keyword to import the Employee class:
import payroll.Employee;
Note:
A class file can contain any number of import declarations. The import declarations must come after the package declaration and before the class declaration.
Directory Structure of Packages
Placing classes in a package has two main effects:
The package name becomes part of the class name, as we discussed earlier.
The package name must match the directory structure where the bytecode resides.
Here is a simple way to manage your Java files:
Place the source code for classes, interfaces, etc., in a file with the name of the type and a .java extension. For example:
// File name: Car.java
package vehicle;
public class Car {
// Class implementation
}
Next, place the source file in a directory that corresponds to the package name.
...\vehicle\Car.java
Now, the correct class name and path will be as follows:
Class name -> vehicle.Car
Path name -> vehicle\Car.java (on Windows systems)
Typically, a company uses the reverse of its internet domain name as its package name. For example, if the internet domain is tutorialpro.org, all package names start with com.tutorialpro. Each part of the package name corresponds to a subdirectory.
For example, if there is a package com.tutorialpro.test that contains a source file called tutorialpro.java, there should be a series of subdirectories like this:
...\com\tutorialpro\test\tutorialpro.java
When compiling, the compiler creates a separate output file for each class or interface defined in the package. The output file is named after the type and has a .class extension. For example:
// File name: tutorialpro.java
package com.tutorialpro.test;
public class tutorialpro {
}
class Google {
}
Now, compile this file with the -d option, as follows:
$ javac -d . tutorialpro.java
This will place the compiled files as follows:
.\com\tutorialpro\test\tutorialpro.class
.\com\tutorialpro\test\Google.class
You can import all classes and interfaces defined in *\com\tutorialpro\test* like this:
import com.tutorialpro.test.*;
The compiled .class files should be placed in directories corresponding to the package names, similar to the .java source files. However, it is not required for the .class file paths to match the .java source file paths. You can arrange the source and class directories separately.
<path-one>\sources\com\tutorialpro\test\tutorialpro.java
<path-two>\classes\com\tutorialpro\test\Google.class
This way, you can share your class directories with other programmers without revealing your source code. Managing source and class files in this manner allows the compiler and the Java Virtual Machine (JVM) to find all types used in your program. The absolute path of the class directory is called the class path. It is set in the system variable CLASSPATH. The compiler and the Java Virtual Machine (JVM) construct the path to the .class file by appending the package name to the class path.
<path-two>\classes is the class path, and the package name is com.tutorialpro.test. The compiler and JVM will look for the .class file in <path-two>\classes\com\tutorialpro\test.
A class path may include several paths, and multiple paths should be separated by a delimiter. By default, the compiler and JVM search the current directory. JAR files contain classes related to the Java platform, so their directories are included in the class path by default.
Setting the CLASSPATH System Variable
Use the following commands to display the current CLASSPATH variable:
Windows platform (DOS command line): C:> set CLASSPATH
UNIX platform (Bourne shell): # echo $CLASSPATH
To clear the CLASSPATH variable:
Windows platform (DOS command line): C:> set CLASSPATH=
UNIX platform (Bourne shell): # unset CLASSPATH; export CLASSPATH
To set the CLASSPATH variable:
Windows platform (DOS command line): C:> set CLASSPATH=C:\users\jack\java\classes
UNIX platform (Bourne shell): # CLASSPATH=/home/jack/java/classes; export CLASSPATH