Java Workshop
 

Java Packages

Jargon

Attribute
A single piece of information that represents a property present in all instances of a class. An attribute is often modeled as a variable in a class.
Byte
The amount of memory space used to store one ASCII character, which is usually 8 bits. A bit is the smallest unit of information a computer can hold; short for binary digit, the value can be either one or zero.
Component
A piece of software with a clear function that can be isolated and replaced by another component with equivalent functionality.
Function
A method that performs some form of processing in order to return a result. For example, a function to calculate the sum of two integers.
Input
Something put into a system or expended in its operation to achieve output or a result.
Library
A library is a collection of subprograms used to develop software. Libraries are distinguished from executables in that they are not independent programs.
Namespace
A scoping construct to subdivide the set of names and their visibility within a system. In many languages, this is tied to other computational constructs, eg, classes, procedures, modules, packages. A mechanism used to resolve naming conflicts.
Performance
A major factor in determining the overall productivity of a system, performance is primarily tied to availability, throughput and response time.
Statement
An entity in a programming language which is typically the smallest indivisible unit of execution.
Sub-class
A class that is an extension of another class and inherits public and protected variables and methods from the other class. Also known as a derived class.

Introduction

In order to provide namespace management Java provides the mechanism of creating Java Packages. A Java Package can be thought of as a collection of Java source files, usually grouped by functionality. In order to utilize Java fully you should understand how packages work.

Java Packages

What is a Package?

One of the many concerns that programmers face today is trying to ensure that their source code does not conflict with the source code of other programmers. A typical example is the case when two programmers define two distinct classes that have the same name. Suppose you decide to write a List class that keeps a sorted list of objects. This would inherently conflict with the List class in the Java API that is used to display a list of items in a Graphical User Interface. Java has a simple solution to this problem that is known as namespace management. Each programmer defines their own namespace and place their code within that namespace, thus two classes that have the exact same name are now distinguishable since they occur in different name spaces. Namespaces are called packages in Java.

Another important reason for using packages is that it provides programmers with greater control over their source code. It is typical to have a few thousand source files in medium to large scale applications, and trying to maintain them would be difficult at best, if not impossible. However, separating these source files into packages makes it much easier to manage the source code. What usually occurs is that related classes are grouped into a single package, for example, all the user interface classes of an application will be grouped into a package.

Access protection is another benefit of using packages. Suppose a group of different applications utilize the same set of source code, it would make sense to separate this source code and maintain it as a separate library that each application uses. In such a library, there is a public interface and a private interface. The public interface is those classes and methods that are accessible to the application using the library, while the private interface is not accessible to the application. Using a package makes it easier to define which classes form part of the public interface and which are part of the private interface. This makes it easy to control access to certain code sections.

Some of the benefits of using packages are:

It shows that the classes and interfaces in the package are related.
Often a group of classes and interfaces are related according to functionality so naturally they should be grouped into a package. An excellent example is the java.io package which groups a set of classes that all perform input and output functions.
You know where to find the classes you want if they're in a specific package.
If you are looking for a specific class and you know what functionality it provides you will naturally be able to find it in the right package. If you are looking for an InputStreamReader you will find it in the input and output package, ie: java.io
The names of your classes and interfaces won't be in conflict with those of other programmers.
If you decide to implement your own String class and you place it in a package it will be distinguishable from the java.lang.String class that comes with the Java API.
You can restrict the access to your classes.
When you only want your code or program to access certain code, for example in a library, then using packages makes access control to source code much easier.

Creating Packages

Creating a Java Package is relatively simple but may seem a bit confusing for people who have not done it before. There are two fundamental requirements for a package to exist:

  • The package must contain one or more classes or interfaces. This implies that a package cannot be empty.
  • The classes or interfaces that are in the package must have their source files in the same directory structure as the name of the package.

Naming Packages

Since packages are used to create namespaces that are used to prevent the problem of name conflicts, namespaces must be unique. This means that package names must be unique. Naming a package is therefore a very important aspect of creating a package.

Often organizations that are involved in software development will use their organi ation's domain name, since domain names by definition are unique. The domain name is inverted to make it easier to read. Good examples can be found from looking at the source code of the Apache Software Foundation, whose domain name is www.apache.org. All their code is placed into packages that have names beginning with org.apache.

Since the Apache Software Foundation has a number of sub-projects, each with its own web address, the project name is also used in the package name. The Ant project can be found at http://ant.apache.org, and it should be no surprise that their code is in the packages with names beginning with org.apache.ant.

When naming your package you should take your inverted domain name, if you have one, and add the project name to it. This will ensure that you have a unique package name, since it is highly unlikely that your organization is working on two projects that have the exact same name. As an example: com.mycompany.myproject

Some companies have decided to drop the top level domain (com, org, net, ...) from their package names for the sake of brevity, this is still perfectly acceptable: mycompany.mypackage

Declaring Package Members

The first thing to do when creating a package is to decide which classes and interfaces should belong to that package. Once you have decided that, you need to specify this by adding a package declaration to the source file of each class and interface that is a part of the package.

The declaration is simple, you use the package keyword followed by the package name. This declaration comes right at the top of the source file, before any import statements.

/*
 * File comments...
 */
 
 package com.mycompany.myproject;
 
 import java.util.*;
 
 class MyClass {
 
 }

Source and Class File Organization

One of the requirements for a package is that the source file should be contained in a directory structure that resembles the name of the package. This is simply creating a set of directories with the names given in the package name.

Take the package name and split it up according to where the periods (.) occur, for example, com.mycompany.myproject can easily be split up into three components, namely: com, mycompany and myproject. These will be the three directories that you create. The first directory will be the com directory and within this directory you will create a sub directory namely the mycompany directory and within that directory a sub directory, namely the myproject directory.

Finally, all the source files that are part of the package will go into the myproject directory.

It is typical in many java project to have the source code go into a src directory and when it is compiled, the resulting byte code goes into a classes directory. The package directories will therefore go into the src directory. As an example, consider a class named MyClass in the package named com.mycompany.myproject and all source code in the src directory. The following picture depicts this situation clearly:

Source Code Organization

Compiling The Package

At first it may seem like a nightmare trying to compile the package, especially having the resulting class files occur in the classes directory, but it can be achieved using a single command. You don't even need all the package directories under the classes directory since they will be created in the compilation.

To try this out, create a test directory and all the sub directories required:

mkdir test
mkdir test\src
mkdir test\classes
mkdir test\src\com
mkdir test\src\com\mycompany
mkdir test\src\com\mycompany\myproject

Now create the MyClass source file named MyClass.java in the test\src\com\mycompany\myproject directory.

/* MyClass.java
 * Author: Trevor Miller
 */
package com.mycompany.myproject;
                                                                                
public class MyClass {
                                                                                
}

Change into the test directory and compile the package:

cd test
javac -d ./classes/ ./src/com/mycompany/myproject/*.java

If you take a look in the classes directory, you will find the exact same directory structure as in the src directory. You'll also find a MyClass.class file in the test\classes\com\mycompany\mypackage directory. This is good as it allows you to keep your source and class files separate and provides greater control over your files.

Source and Class Organization

Using Packages

Once you have created your package you may want to use it in your program or you may wish to use another programmer's package or the packages in the Java API. There are three ways of using the resources in a package; inline package member declarations, importing only the package member that you want and importing the entire package.

Inline Member Declarations

In this approach you simply declare the package member you wish to use with its fully qualified package name. As an example, suppose you wish to use the Vector class in the java.util package. You can easily declare a vector using java.util.Vector vector;

When you initialize the object by calling its constructor, you will again have to use the fully qualified package name.

class Test {
   java.util.Vector vector;
   
   Test() {
      vector = new java.util.Vector();
   }
}

Importing a Single Package Member

Using the inline declaration works well if you only use it a few times in your source code, but it can become a pain to type the fully qualified package name if you use it often. Instead you want to do this once and only once, and from then on, simply use the member's name wherever you need it.

This is easily achieved using an import statement in which the import keyword is followed by the fully qualified name of the member you wish to use. Consider the example given previously, but revised to use this method:

import java.util.Vector;
class Test {
   Vector vector;
   
   Test() {
      vector = new Vector();
   }
}

Importing an Entire Package

It may be that you use a number of members from a package and end up with a large number of import statements. As an example consider the following:

import java.util.Vector;
import java.util.LinkedList;
import java.util.Hashtable
import java.util.Stack
import java.util.Set

class Test {
   ...
}

This can become messy quite quickly, and you would like to get away from this. The answer is to simply import the entire package, again using the import statement but instead of declaring the member you use a wildcard symbol to indicate that everything should be imported. The wildcard symbol is an asterisk (*), using this method you can replace all the import statements of the previous example with simply one import statement.

import java.util.*;

class Test {
   ...
}

As you can see, this is much cleaner but it does have its limitations. If the package is very large and you import everything in the package, this will impact the performance of your program. You should consider carefully whether greater clarity in your code and ease of writing the code outweighs the addition of some overhead to the performance of your application.

Summary

Packages are a great way to organize your source code and split source code from byte code (class files). Understanding how packages work is vital to writing quality software.

Exercise Set

Multiple Choice

  1. Namespaces are used to:

    1. Control access to classes.
    2. Resolve naming conflicts among programmers.
    3. Bundle a set of classes together.
  2. Which is not a benefit of using packages?

    1. Finding the classes you want is difficult.
    2. Access protection.
    3. Separation of source and class files.
  3. To create a package named "za.co.nephila.maculata" you would use which statement?

    1. package maculata
    2. package nephila.maculata
    3. package za.co.nephila.maculata
  4. To import the ChatServer member of the Maculata package (za.co.nephila.maculata) you would use:

    1. import maculata.*;
    2. import za.co.nepihla.maculata.*;
    3. import za.co.nephila.maculata.ChatServer;
  5. The classes of the Maculata package (za.co.nephila.maculata) will be in which directory?

    1. /Maculata/classes
    2. /Maculata/classes/za/co/nephila/maculata
    3. /Maculata/src/za/co/nephila/maculata

Exercises

  1. Take a look at the Java API and see how the packages are structured.

Programming Exercises

  1. Complete the following:
    1. Create a package named org.shapes.
    2. Create some classes in the package representing some common geometric shapes like Square, Triangle, Circle and so on.
    3. Finally compile the package as discussed in this chapter.