Package Statements in Java Source Files
An import directive lets you write a simple class name in the rest of a Java file instead of the full name, but it does not change the class or its type.
Why Full Names Get Heavy
Suppose you want to use the Color class from the java.awt package in a program. Its full name is java.awt.Color, and that full name is what Java needs in order to identify the class exactly. Writing the full name everywhere is precise, but it is heavy. A program that uses several classes from several packages quickly becomes hard to read.
Java offers a way to keep the precision while writing shorter names in the body of your code. That mechanism is the import directive. This article looks at how it works, where it has to sit in a file, how far its wildcard form reaches, and how to spot the point where a simple name stops working.
What do you think happens?
Before reading on: if you import java.awt.Color, does the class itself change, or does only the way you write its name change?
Reveal answer
Only the way the name is written in the file changes.
The import does not change the class or its type. It only allows the shorter spelling in the file where the directive appears.
Tracing Where a Simple Name Fails
Follow a short program from top to bottom. The first line is the package statement. The class body declares a variable named rectColor of type Color, written as a simple name. Without any import directive, the simple name Color has no link to a full name at that point in the file, so the declaration cannot be resolved as intended.
Read the diagram as a trace. The program is correct up to the declaration. The failure is not in the class body as such. It happens because the simple name at the declaration has not been connected to a full name. Adding an import directive between the package line and the class body changes the answer at the decision point, and the same declaration then resolves.
What the Import Directive Actually Does
An import directive lets you write a simple class name in the rest of a Java file instead of the full name. It does not change the class or its type. Although people often call an import line a statement, it is more properly called an import directive, because it is not a statement in the ordinary sense.
public class Demo {
java.awt.Color rectColor;
}The type is written as the full name java.awt.Color.
import java.awt.Color;
public class Demo {
Color rectColor;
}The type is written as the simple name Color, and the import line connects it to java.awt.Color.
Look closely at what changed between the two versions. Only the name written in the body of the file changed. The class being declared stays the same, the type of rectColor stays the same, and the import only allows the shorter spelling in the file where the directive appears. Keeping this distinction clear helps when you read errors later, because a correctly spelled name can still fail if the directive it depends on is missing or misplaced.
Placing the Directive in a File
The directive has a fixed place. It appears at the start of the file, after the package statement if the file has one, and it sits outside any class. Its scope is the whole file, so once you place it, every later use of the simple name in that file is covered.
- The package statement is first, if the file has one.
- The import directive sits after the package statement and before the class.
- The simple name Color inside the class body is covered by the import for the whole file.
How Far a Wildcard Import Reaches
An import directive does not have to name one class. The wildcard form uses an asterisk in place of the class name, written after the dot in the package name. The wildcard matches every class in the named package, so one line abbreviates many class names at once without a separate import line for each class.
- The wildcard covers classes directly inside
java.util. - It does not cover classes inside subpackages of
java.util.
The wildcard is precise, and it is easy to misjudge. Many learners first assume a star written at the java level is a broad, recursive gesture that brings in every class beneath it, including classes in every nested package. The source rejects that reading. A wildcard import matches every class in the named package, but it does not match subpackages. So java.* does not import the contents of all subpackages of java, and java.util.* does not import java.util.function or java.util.concurrent.
Mistakes That Break Simple Names
When a program breaks after you switch to a simple class name, the cause is usually one of a few specific things. Use this list as a checklist when you read the output of a failed build.
Common mistake Suspecting the declaration first when a simple name fails
Why it failsThe declaration is often correct. The failure usually comes from the import directive being missing, misplaced, or naming the wrong package.
Do this insteadCheck where the import directive sits and which package it names before you change the declaration.
Common mistake Placing the import inside the class body
What it looks likepublic class Demo { import java.awt.Color; Color rectColor; }Why it failsThe directive has a fixed place outside any class.
Do this insteadMove the import above the class declaration, after the package statement if there is one.
Common mistake Expecting a wildcard to reach subpackages
What it looks likeimport java.util.*; then using Function from java.util.functionWhy it failsA wildcard matches every class in the named package but does not match subpackages.
Do this insteadAdd a separate import for the subpackage, such as an import for the Function class in java.util.function.
Common mistake Believing the import changes the class
Why it failsThe import does not make the class available under a different identity or change its type.
Do this insteadTreat the import as a change to how the name is written in this file only.
Worked Example: Finding the Failing Line
Locating where a simple name stops resolving
A file contains the package line, a class Demo, and the declaration Color rectColor inside the class body, with no import directive. Where does the simple name stop resolving, and how is it fixed?
- 1Read the file from the top
The package statement is the first line, and it is valid. Nothing has yet connected the simple name Color to a full name.
- 2Reach the declaration
The declaration Color
rectColorappears in the class body. The simple name Color is used here, and no import directive has appeared earlier in the file to supply the full name. - 3Identify the failing point
The name stops resolving at the declaration, not at the package line. The problem is the missing link between the simple name and
java.awt.Color. - 4Add the directive in the right place
Insert import
java.awt.Color; after the package statement and before the class declaration. The declaration itself does not need to change. - 5Confirm the result
Now the simple name Color is covered by the directive for the whole file. The class and the type of
rectColorare unchanged.
The name fails at the declaration because no import connects Color to its full name. Adding the directive after the package statement and outside the class fixes it without changing the class.
Practice: Predicting Wildcard Reach
A file contains import java.util.*; and the class body uses the simple name Scanner. Then the same file uses the simple name Function, which lives in java.util.function. Without any other import, predict which name resolves and explain why, using the rule about subpackages.
Hints
- Ask whether Scanner is directly inside
java.util. - Ask whether Function is directly inside
java.utilor inside a subpackage of it. - Remember that a wildcard matches every class in the named package but not its subpackages.
Key Takeaways
- An import directive lets you write a simple class name in the rest of a Java file instead of the full name, but it does not change the class or its type.
- The directive belongs at the start of the file, after the package statement if present, and outside any class, and it covers the whole file.
- A wildcard import with an asterisk matches every class in the named package but does not match subpackages, so java.* does not import the contents of all subpackages of java.
- When a simple name fails, check where the import directive sits and which package it names before suspecting the declaration itself.