SECTION 1
Historical Context & Motivation
As programming languages matured through the 1980s and 1990s, projects grew from a few hundred lines of code to millions. Developers quickly realized they needed a way to organize classes into logical groups, much like organizing files into folders on your computer. Without such a system, two programmers on the same project could accidentally give different classes the same name, causing conflicts that were painful to resolve.
When James Gosling and the team at Sun Microsystems designed Java in the early 1990s, they borrowed the concept of packages from earlier languages like Modula-2 and Ada. Packages give every class a unique address—its fully qualified name—so that name collisions become virtually impossible. The import statement was introduced as a convenience so that programmers wouldn't have to type out long package paths every single time they used a class.
1970s • Modular Programming Emerges
1995 • Java 1.0 Released
2004 • Java 5 — Static Imports
2017 • Java 9 — Module System
The fundamental question Java's package-and-import system addresses is: How do you give every class a unique identity while still keeping your code short and readable? Understanding imports and qualified names is the answer to that question, and it's a skill you'll use in every Java program you write.
SECTION 2
Core Principles & Definitions
Before you can use a class from the Java standard library—or from any external library—you need to tell the compiler where to find it. Java provides two main approaches: writing the class's full package path every time (its fully qualified name), or declaring an import at the top of your file so you can use just the short class name. Let's define the key ideas you'll need.
Package
java.util contains utility classes like ArrayList and HashMap. Think of a package as a folder in a file system.Fully Qualified Name (FQN)
java.util.ArrayList is the FQN for ArrayList. It's like a full mailing address—city, street, and house number.Import Statement
import java.util.ArrayList; lets you type just ArrayList everywhere in the file.Wildcard Import
import java.util.*; imports all classes from a package at once. It's convenient but can sometimes cause ambiguity if two packages share a class name.java.lang — The Automatic Import
java.lang (like String, Math, Integer, and System) are automatically imported in every Java file. You never need to write an import for them.KEY TAKEAWAY
SECTION 3
Visual Explanation — How Packages & Imports Connect
The diagram below shows how a Java source file relates to the package tree. On the left you see the package hierarchy, and on the right you see how your code references classes from those packages through either an import statement or a fully qualified name.
java.util and java.io. The source file (right) uses import statements for ArrayList and Scanner, enabling short names. The File class is used with its fully qualified name because there is no import for it.Notice how the dashed arrows connect each class in the package tree to where it appears in the source code. The cyan arrows represent classes brought in through import statements, while the amber arrow shows a class accessed through its fully qualified name. Both methods work correctly—the choice depends on how often you use the class and whether you want cleaner code or more explicit references.
SECTION 4
How Imports & Qualified Names Work Under the Hood
It's important to understand that import statements do NOT load or copy code into your file. They are purely a convenience for the compiler. When you write import java.util.ArrayList;, you're telling the compiler: "Whenever I write ArrayList, I mean java.util.ArrayList." The compiled bytecode is identical whether you use an import or the fully qualified name.
The Three Forms of Class Reference
Java gives you three syntactic approaches to reference a class from another package. Each has its place.
1. Single-Type Import
The single-type import imports exactly one class. This is the most common and recommended form. You write import java.util.ArrayList; at the top of your file, and then use ArrayList by itself anywhere in the file. It makes your code clear because anyone reading it can see exactly which classes you depend on.
2. Wildcard Import
The wildcard import uses an asterisk to import every class from a package: import java.util.*;. This is convenient when you need many classes from the same package. However, it does NOT import sub-packages. Writing import java.*; does not give you classes from java.util or java.io.
3. Fully Qualified Name (Inline)
You can skip the import entirely and use the fully qualified name right in the code: java.io.File myFile = new java.io.File("data.txt");. This is most useful when you only use a class once or twice, or when two packages contain classes with the same name and you need to disambiguate.
Common Pitfall: Name Collisions
java.util and java.sql contain a class called Date. If you wildcard-import both packages, the compiler won't know which Date you mean. The fix: use a single-type import for the one you use most, and the fully qualified name for the other.SECTION 5
Syntax Details & Classification
Let's look at every type of import statement side by side, with syntax rules and key notes. The table below serves as a quick-reference guide you can return to while coding.
| Import Type | Syntax Example | What It Does | When to Use |
|---|---|---|---|
| Single-type | import java.util.ArrayList; | Imports one specific class | Default choice; clear and precise |
| Wildcard | import java.util.*; | Imports all classes in a package | When using many classes from one package |
| Static | import static java.lang.Math.PI; | Imports a static field or method | When using constants/methods from a utility class repeatedly |
| Fully Qualified | java.io.File f = ...; | No import; uses full path inline | Rare usage or resolving name collisions |
| Auto-imported | (no statement needed) | java.lang.* is always available | String, Math, System, Integer, etc. |
Summary of all import types in Java
Rule of File Structure
SECTION 6
Worked Example — Building a Student Roster Program
Let's walk through a realistic example. Suppose you're writing a program that reads student names from the keyboard, stores them in a list, sorts them alphabetically, and writes the result to a file. You'll need classes from multiple packages.
Creating a Sorted Student Roster
- 1
Step 1 — Identify the Classes You Need
Think about what operations you'll perform. Reading keyboard input requiresjava.util.Scanner. Storing a dynamic list of names requiresjava.util.ArrayList. Sorting requiresjava.util.Collections. Writing to a file requiresjava.io.PrintWriter.Four classes needed from two packages: java.util and java.io - 2
Step 2 — Write the Import Statements
Since you need three classes fromjava.util, you could use three single-type imports or one wildcard import. Since you only need one class fromjava.io, a single-type import is clearest. Your imports would look like this:import java.util.ArrayList;,import java.util.Collections;,import java.util.Scanner;, andimport java.io.PrintWriter;.Four import statements placed before the class definition - 3
Step 3 — Use Short Names in the Class Body
Inside your class, you can now writeScanner input = new Scanner(System.in);andArrayList<String> roster = new ArrayList<>();without any package prefixes. Notice thatStringandSystemdon't need imports because they're injava.lang.Short names like Scanner, ArrayList, and PrintWriter work everywhere in the file - 4
Step 4 — Sort and Write Output
After collecting names in a loop, callCollections.sort(roster);to sort alphabetically. Then create aPrintWriter out = new PrintWriter("roster.txt");and loop through the roster to write each name. Close the writer without.close();.Complete program uses four imported classes cleanly, with no fully qualified names needed
Alternative Approach
java.util imports with a single import java.util.*;. The compiled program behaves identically. However, many coding style guides (and AP CS conventions) prefer single-type imports because they make dependencies more explicit.SECTION 7
Comparing Import Strategies
Each approach to referencing classes has trade-offs. The table below summarizes the strengths and limitations of each strategy so you can make informed decisions in your own projects.
| Strategy | Strengths | Limitations |
|---|---|---|
| Single-type import | Explicit; easy to see dependencies; avoids name collisions; preferred by most style guides | Can lead to long import lists in large programs |
| Wildcard import | Shorter import section; convenient when using many classes from one package | Can cause ambiguity if two wildcarded packages share a class name; harder to see what's actually used |
| Fully qualified name | No import needed; unambiguous; resolves name collisions instantly | Very verbose; clutters code if used repeatedly |
| Static import | Reduces repetitive class prefixes for utility methods and constants (e.g., Math.PI becomes PI) | Overuse can make it unclear where a method or constant comes from |
Trade-offs of each import strategy in Java
KEY TAKEAWAY
SECTION 8
Connection to Advanced Concepts
The import system you've learned is the daily workhorse of Java programming, but it sits within a larger ecosystem that you'll encounter as you advance. Understanding how imports connect to more sophisticated features will prepare you for AP Computer Science topics and college-level Java development.
| Concept You Learned | Advanced Extension | Why It Matters |
|---|---|---|
| Packages group related classes | Java Modules (Java 9+) group related packages | Modules add a higher level of access control and dependency management |
| Import resolves short names at compile time | Class loading loads bytecode at runtime | The JVM's ClassLoader dynamically finds and loads .class files when they're first needed |
| Wildcard imports can cause name collisions | Dependency management tools like Maven and Gradle | Build tools automatically manage which library JARs are available, preventing classpath conflicts at scale |
| Static imports for utility methods | Framework annotations and dependency injection | Frameworks like Spring use annotations and automatic scanning to wire classes together, going beyond manual imports |
How today's concepts connect to advanced Java development
For now, focus on mastering single-type imports and knowing when to reach for a fully qualified name. These fundamentals will carry you through AP Computer Science A and beyond. As your projects grow, tools like IDEs (Integrated Development Environments) such as IntelliJ IDEA and Eclipse can automatically manage your import statements, but understanding what they do behind the scenes is essential for debugging and writing code on exams.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
String can be used in any Java file without an import statement, but ArrayList cannot. What is special about the package that String belongs to?Show answer
java.lang package, which Java automatically imports into every source file. This is the only package that receives this special treatment. ArrayList, on the other hand, belongs to java.util, which is not auto-imported. Because java.lang contains the most fundamental classes (String, System, Math, Integer, etc.), the language designers decided to always import it so that every program could use these essentials without extra boilerplate.Question 2: BASIC
public class Quiz { public static void main(String[] args) { HashMap<String, Integer> scores = new HashMap<>(); Scanner kb = new Scanner(System.in); } }Show answer
import java.util.HashMap; and import java.util.Scanner;. Both HashMap and Scanner are in the java.util package. String and System don't need imports because they're in java.lang. Integer also doesn't need an import for the same reason. These two import statements should be placed before the class definition.Question 3: INTERMEDIATE
import java.util.*;
import java.sql.*;
public class Report {
Date today = new Date();
}Show answer
java.util and java.sql contain a class named Date. When both packages are wildcard-imported, the compiler doesn't know which Date you mean. Fix 1: Replace one wildcard with a single-type import. For example, keep import java.sql.*; but change the other to import java.util.Date;. The single-type import takes precedence over the wildcard. Fix 2: Use the fully qualified name in the code itself: java.util.Date today = new java.util.Date();. Both solutions eliminate the ambiguity.Question 4: APPLIED
java.io.File, java.io.PrintWriter, java.util.Scanner, java.util.ArrayList, and java.util.Collections. Write the complete set of import statements. Would a wildcard import for java.util be reasonable here? Justify your answer.Show answer
import java.io.File;, import java.io.PrintWriter;, import java.util.ArrayList;, import java.util.Collections;, import java.util.Scanner;. A wildcard import for java.util.* would be reasonable here because you're using three classes from that package, which is a significant number. It would reduce five import lines to three. However, if your project also uses java.sql, the wildcard could introduce ambiguity with shared class names like Date. In this case, since no other packages conflict, the wildcard is acceptable.Question 5: CRITICAL THINKING
Show answer
SUMMARY
Lesson Summary
Summary
Java organizes classes into packages—logical namespaces that prevent name collisions and keep large codebases orderly. Every class has a fully qualified name (FQN) that includes its package path (like java.util.ArrayList). To avoid typing the full path repeatedly, you place import statements at the top of your file. A single-type import (e.g., import java.util.Scanner;) is the clearest and most recommended form. A wildcard import (e.g., import java.util.*;) brings in all classes from a package at once but can cause ambiguity.
Classes in java.lang (like String, Math, and System) are auto-imported and never need an import statement. When two packages contain a class with the same name, use the FQN inline or a single-type import to resolve the conflict. Remember that imports are a compile-time convenience only—they don't affect performance or load extra code. A Java file follows a strict structure: package declaration → imports → class definition.