I posed this homework assignment in my Spring 2003 graduate
programming language class. You will first find the statement of the
assignment. My solution (which the students did not see until after the
due date) is at the end of this article. If you are impatient and just
want to clean your import statements, go to the end of this document
and download the program.
In case you are curious . . . the students did rather well. The
majority of the students independently produced correct solutions, and
one of them found a subtle error in mine.
In the Java programming language, the names of classes that are defined inside packages always start with the package name. For example, the class name
java.awt.Rectangle
starts with the name of the package java.awt. As a
convenience to programmers, the import mechanism can be used
to
reference classes without the package name. For example, it is tedious
to write
java.awt.Rectangle box = new java.awt.Rectangle(5, 10, 20, 30);
You can use the more convenient form
Rectangle box = new Rectangle(5, 10, 20, 30);
provided you import the class.
Classes in the same package are automatically imported, as are the
classes in the java.lang package. For all other classes, you
must supply an import statement to either import a specific class
import java.awt.Rectangle;
or to import all classes in a package, using the on demand
notation
import java.awt.*;
Importing classes can lead to ambiguities. A class name is
ambiguous if it occurs in two packages that are imported on demand. For
example, suppose a program contains the imports
import java.awt.*;
import java.util.*;
The class name List is now ambiguous because there are two classes java.awt.List and java.util.List. You can resolve the ambiguity by adding a specific import of the class name:
import java.awt.*;
import java.util.*;
import java.util.List;
However, if you need to refer to both java.awt.List and java.util.List
in the same source file, then you have crossed the limits of the import
mechanism. You can use an import statement to shorten one of
the names to List, but you need to reference the other by its
full name whenever it occurs in the source text.
Ambiguities are unpleasant because they can arise over time, as libraries expand. For example, in JDK 1.1, there was no java.util.List class. Consider a program that imports java.awt.* and java.util.* and uses the name List as a shortened form of java.awt.List . That program compiles without errors under JDK1.1 but fails to compile in Java 2.
Therefore, the use of import on demand is somewhat dangerous. However, single class importing can lead to long import lists that are tedious to manage, especially as code is moved from one class to another during development.
To illustrate this, consider the import list in one of my recent
files.
import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
It turned out that I really needed
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
(Apparently, the need for importing java.io.* had gone away at some point during the program's evolution)
Thus, a problem that Java programmers face is how to keep import lists up-to-date when programs change.
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
Sort the list alphabetically.
You may assume that the source file is syntactically correct. You
may further assume that all classes in the source file and all classes
on which they depend have already been compiled and can be loaded.
import javax.swing.*;
public class Test
{
public static void main(String[] SwingConstants)
{
System.out.println(SwingConstants.length); // don't generate import
}
}
import javax.swing.*;
public class Test
{
public static void main(String[] SwingConstants)
{
class Foo implements SwingConstants {}; // generate import javax.swing.SwingConstants
System.out.println(Foo.EAST);
}
}
import java.net.*;
public class Test extends javax.print.DocFlavor
{
public Test() { super("", ""); }
public static void main(String[] args)
{
System.out.println(URL.AUTOSENSE); // don't generate import
}
}
Class cl = Class.forName(...);This is important because Class.forName will load non-public classes (such as java.awt.Queue).
if (Modifier.isPublic(cl.getModifiers()) ...
The program takes the following options: