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 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
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.
You import packages/classes not files.
import com.mindprod.common18. Build;
not
import
J:\com\mindprod\common18\Build.java
;
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.*.
- You can’t use wildcards on partial names, e.g. import java.awt.Text*;
- You can teach your IDE (Integrated Development Environment) to handle your
imports for you. This save a great deal of mindless busywork.
- It is a good idea to avoid wildcards, unless you have a very large number of
classes. The list of explicit imports is great documenation on just what sorts of
thing the class is doing/could potentially do.
- 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 the 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 on one page. 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.
Missing import Mystery
I was puzzled discovering progams without imports for classes used that still worked. You don’t need an
import a class unless you use the methods of a class or
mention the class name explicitly. If you just pass the result of some method
directly as a parameter to another method, without mentioning the class name of the
object explicitly, you don’t need an import.