Because of the rigid source code naming convention, the Java compiler can
easily find the corresponding source or class files just from the fully
qualified name of a package and class. By fully qualified name I mean specifying
the full package and class e.g.
java.util.ArrayList x = new java.util.ArrayList ( 149 );
The alternative to this long-winded style of coding, is to use import statements.
A typical set of import statements might look like this:
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Properties;
They must come right after the package statement,
before the class statement. They are traditionally
kept sorted in alphabetical order. Then you can code in an abbreviated style:
ArrayList x = new java.util.ArrayList( 149 );
Unlike C or C++ we do not need to include headers to help the compiler determine
what sorts of parameters other routines want; it can go look for itself in the
source or class files. The import statement is not like the C++ include.
So long as you fully qualify your reference in the code to class names with com.mindprod.mypackage.myClass
there is no need for imports. They just allow shorthand. Even when you do have
an import, you can still fully qualify your references to classes.
Let us say your package is called com.mindprod.mypackage
and your class is called MyClass. There are two forms
of the import statement:
- import com.mindprod.mypackage.MyClass;
- import com.mindprod.mypackage.*;
Then you can refer to the class as plain MyClass,
static methods as MyClass.myStaticMethod() and static
variables and constants as MyClass.myStaticValue,
without the com.mindprod.mypackage qualification.
There is no form of the import that lets you get away with coding your
references without MyClass. e.g. just myStaticMethod()
or myStaticValue. The most common problems with import
are:
- failing to get upper/lower case precisely correct in the import statement
package and classnames.
- failing to get upper/lower case precisely correct in the matching directories
and *.java names. See classpath
for more details.
- failing to name each source module as X.java where X
is the name of the public class defined in that source file.
- Your imports must be accessible via the CLASSPATH.
- Mismatch of CLASSPATH and import. The more qualification you specify in the
CLASSPATH, the less you are allowed to specify in the import statement.
You may not specify a directory both in the import and in the CLASSPATH. The
import gives the lower levels of qualification the CLASSPATH the higher. Another
way of stating this is your CLASSPATH should point to the directory just above
the one named for your package’s highest level of qualification.
- Wildcards are not as wild as you might expect causing you to fail to import each
package branch separately. import java.awt.*; does not
automatically import java.awt.event.* as well. You
must separately import java.awt.event.*.
- If you have a class name used in more than one package, you will save yourself a
lot of grief if you always fully qualify references to it, rather than relying
on import. The computer may understand but, your fellow programmers will often
be confused by tha lack of qualification. Beware of java.util.List
and java.awt.List.
- Never use a classname (either in your package or in your anonymous package) that
is also used in some other package. You are just begging for trouble. In theory
the purposes of packages is to protect against name clashes, but as soon as you
use import that protection is gone.
- Package names should be pure lower case. Class names should begin with an upper
case letter. Violating this convention will confuse the heck out of anyone
trying to decipher your code.
- You can write simple programs leaving out the package statement. However, this
should only be used for programs that fit in one file. You
can’t use classes in the default package from a named package. So except
for tiny experiments, always put your classes in a named package of the form com.mindprod.xxx
or org.hans.xxx i.e. your domain name backwards,
all lower case.
- You must not import classes in the same package as the current class. If you are
using the default nameless package, you must not import any other classes in the
default package.
For a discussion of the philosophy when to use imports and when to use
qualification see the import
tidier student project.
It is a great help to understanding someone else’s code, (or even your own),
if you refrain from using the .* style of import with the imports giving you an
explicit list of the classes you use in that class. The list of explicit imports
gives you a rough idea of what the class could do and what it is likely
up to. Don’t leave unused imports lying around. Use an import
tidier, or Eclipse, to get rid of them, and sort
the valid ones into alphabetical order. During development, it is fine to use
the lazy .* form, (doing so will save you a ton of compiler errors), but once
your work gels, convert over. Bon’t camouflage your use of classes by
fully qualifying them and not reporting them in the import. The only time you
need qualification is when there is a name clash, e.g. java.awt.List
and java.util.List.
The other problem with using wildcards is this. Let’s say you use import
java.awt.* to get your Label
class. Then later somebody using your code has a com.wombat.superawt.
Label class on their classpath. The code won’t
compile, or worse, it will use the wombat Label
class in place of the awt Label class without
telling anyone.