Packages: Commentary

Steven Zeil

Last modified: Jun 16, 2020
Contents:

****

A package is a container of related classes and smaller packages.

1 Creating and Using Packages

The Java package is very similar to the C++ namespace, but is used much more often than its C++ counterpart.

1.1 Creating a Package

In a C++ namespace, all classes are “public”. Java’s ability to have some items in the namespace package private, visible only to other classes within the same package, has no equivalent in C++.

1.2 Naming a Package

Software released from our Dept would typically be in packages starting with edu.odu.cs. For example, the ODU Metadata Extraction project released code in the package edu.odu.cs.extract, and I have released my algorithm animation engine, AlgAE, under package edu.odu.cs.algae.

1.3 Using Package Members

A syntax difference here between C++ and Java: C++ uses :: to select members of a namespace. Compare, for example, std::vector and std::cout in C++ to java.util.Vector and java.lang.System.out in Java. Java is simpler in this regard. C++ programmers often stumble over when to use “::” and when to use “.”.

It’s tempting to guess that the Java import statements are similar to #include in C++. But, actually, that’s not true. Java doesn’t have or need anything equivalent to an #include. That’s because, given the Java rules that packages map onto directories and class names map onto file names, the Java compiler can find any source code it wants just given the (full) name of the class. Suppose that you are writing a program and suddenly realize that you want to use a vector. In C++, if simply add

std::vector<int> myVector;

without inserting a prior #include <vector>, you’ll get an error message.

But in Java, if you simply add

java.util.Vector<int> myVector;

and nothing else, that’s just fine. The compiler knows where to find the class. And that’s not because it’s a “predefined” part of the language. The same would be true if you had your own version:

myOwnPackage.SpecialVector<int> myVector;

What the Java import statements do is to allow you to refer to things by abbreviated names instead of giving the fully qualified name with all enclosing packages.

So Java import statements are actually analogous to the C++ using statements:

Java C++
import java.util.Vector; using std::vector;
import java.io.*; using namespace std::relops;

1.4 Managing Source and Class Files

We’ve talked before about the close relationship in Java between program structure and file structure. It’s worth repeating here, because this is one of the things that takes C++ programmers by surprise:

For example, on one of my projects, I have a class edu.odu.cs.AlgAE.Client.Layout.Anchors. I would find the source code for that in edu/odu/cs/AlgAE/Client/Layout/Anchors.java and the compiled object code in edu/odu/cs/AlgAE/Client/Layout/Anchors.class. Similarly, I have a class edu.odu.cs.AlgAE.Server.MenuGenerator stored in edu/odu/cs/AlgAE/Server/MenuGenerator.java.

This is a noticeable difference from C++. C++ programmers tend to have one flat directory for all their .cpp files and, possibly, one other flat directory for their .h files. Java programmers tend to make much more use of package and directory hierarchies to organize their code.

Now, paths like edu/odu/cs/AlgAE/Client/Layout/Anchors.java are relative directories – they tell you how to find something if you know where to start from. In Java, the starting point when the java or javac commands search for your code is the CLASSPATH. This is an environment variable containing a list of directories and/or jar files. The Java compiler or JVM looks in each directory or jar file in that list for something matching the pattern you gave it.

So, suppose that you are writing a large project that uses some libraries of code that you have obtained from someone else. These libraries aren’t part of your own project so you don’t want to copy all the library code into your project directory. Aside from the possible legal/ethical issues in doing that, making copies like that makes it trickier to keep track of what needs to be done if the authors of the library issue an updated version with relevant bug fixes. So, instead, you want to add the library to your CLASSPATH so that Java will find any references you write to it.

You can do this by directly manipulating the CLASSPATH, e.g., in tcsh:

setenv CLASSPATH path-to-to-library:$CLASSPATH

or in bash:

export CLASSPATH=_path-to-to-library_:$CLASSPATH

In these commands I have added the path to the new library on front of whatever value the $CLASSPATH variable already holds. After that, any java or javac commands issued in that session would search the library.

Adding one or two directories to the front of the existing CLASSPATH is such a common, operation, however, that the java and javac commands provide a special option, -cp, for that purpose:

javac -cp path-to-to-library MyClassName.java

java -cp path-to-to-library MyClassName

In fact, we have previously discussed the -cp option as a way of searching a jar for code to be executed.

1.5 Summary of Creating and Using Packages