The Java package is very similar to the C++ namespace, but is used much more often than its C++ counterpart.
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++.
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
.
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; |
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:
If you have a Java class MyClass
, it must be stored in a file named MyClass.java
.
If your Java class is inside a package myPackage
, then the Java source code must be stored inside a directory named myPackage
.
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.
CLASSPATH
includes your current directory (.
) and the locations of the basic Java pre-installed libraries.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.