JAVA • FUNCTIONS AND PROGRAM STRUCTURE

Imports & Qualified Names — Import classes and use fully qualified names when needed

Learn how Java organizes thousands of classes into packages and how import statements give your code clean, readable access to them.

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
Languages like Modula-2 introduce the idea of modules—separate, self-contained units of code that can be imported into other programs.
1995
Java 1.0 Released
Java launches with a built-in package system and the import keyword. The standard library ships with packages like java.lang, java.util, and java.io.
2004
Java 5 — Static Imports
Java 5 adds 'import static', allowing programmers to import individual static methods and constants without qualifying them with the class name.
2017
Java 9 — Module System
Project Jigsaw introduces modules, a higher-level grouping above packages. Imports and qualified names remain the everyday mechanism for accessing classes.

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.

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.

1

Package

A namespace that groups related classes together. For example, java.util contains utility classes like ArrayList and HashMap. Think of a package as a folder in a file system.
2

Fully Qualified Name (FQN)

The complete path to a class, including its package. For example, java.util.ArrayList is the FQN for ArrayList. It's like a full mailing address—city, street, and house number.
3

Import Statement

A declaration at the top of a Java file that tells the compiler which class you want to use by its short name. Writing import java.util.ArrayList; lets you type just ArrayList everywhere in the file.
4

Wildcard Import

Using 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.
5

java.lang — The Automatic Import

Classes in 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
Think of a fully qualified name like a phone number with the country code and area code included—it always works but is long to dial. An import statement is like saving that number as a contact: once saved, you just tap the name. Both reach the same class; imports simply save you typing.

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.

The package tree (left) shows classes organized under 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.

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
Both 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.

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.

Summary of all import types in Java
Import TypeSyntax ExampleWhat It DoesWhen to Use
Single-typeimport java.util.ArrayList;Imports one specific classDefault choice; clear and precise
Wildcardimport java.util.*;Imports all classes in a packageWhen using many classes from one package
Staticimport static java.lang.Math.PI;Imports a static field or methodWhen using constants/methods from a utility class repeatedly
Fully Qualifiedjava.io.File f = ...;No import; uses full path inlineRare usage or resolving name collisions
Auto-imported(no statement needed)java.lang.* is always availableString, Math, System, Integer, etc.
A Java source file has a strict ordering: ① package declaration (optional), then ② import statements, then ④ class definitions. You cannot place imports inside a class or after it.
📐 Rule of File Structure
The order inside a Java file is always: package → imports → class. The package declaration (if present) must be the very first non-comment line. Imports come next. The class definition follows. Violating this order causes a compile error.

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 NeedThink about what operations you'll perform. Reading keyboard input requires java.util.Scanner. Storing a dynamic list of names requires java.util.ArrayList. Sorting requires java.util.Collections. Writing to a file requires java.io.PrintWriter.
Four classes needed from two packages: java.util and java.io
2
Step 2 — Write the Import StatementsSince you need three classes from java.util, you could use three single-type imports or one wildcard import. Since you only need one class from java.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;, and import java.io.PrintWriter;.
Four import statements placed before the class definition
3
Step 3 — Use Short Names in the Class BodyInside your class, you can now write Scanner input = new Scanner(System.in); and ArrayList<String> roster = new ArrayList<>(); without any package prefixes. Notice that String and System don't need imports because they're in java.lang.
Short names like Scanner, ArrayList, and PrintWriter work everywhere in the file
4
Step 4 — Sort and Write OutputAfter collecting names in a loop, call Collections.sort(roster); to sort alphabetically. Then create a PrintWriter out = new PrintWriter("roster.txt"); and loop through the roster to write each name. Close the writer with out.close();.
Complete program uses four imported classes cleanly, with no fully qualified names needed
💡 Alternative Approach
You could replace the three 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.

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.

Trade-offs of each import strategy in Java
StrategyStrengthsLimitations
Single-type importExplicit; easy to see dependencies; avoids name collisions; preferred by most style guidesCan lead to long import lists in large programs
Wildcard importShorter import section; convenient when using many classes from one packageCan cause ambiguity if two wildcarded packages share a class name; harder to see what's actually used
Fully qualified nameNo import needed; unambiguous; resolves name collisions instantlyVery verbose; clutters code if used repeatedly
Static importReduces 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
✦ KEY TAKEAWAY
Think of single-type imports like a grocery list that names every item: it's clear and organized. Wildcard imports are like writing "everything from the dairy aisle"—faster to write but vague. Fully qualified names are like giving the full GPS coordinates every time—always accurate but tedious. Use the right tool for the situation: single-type imports for most cases, fully qualified names for name collisions, and wildcards sparingly.

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.

How today's concepts connect to advanced Java development
Concept You LearnedAdvanced ExtensionWhy It Matters
Packages group related classesJava Modules (Java 9+) group related packagesModules add a higher level of access control and dependency management
Import resolves short names at compile timeClass loading loads bytecode at runtimeThe JVM's ClassLoader dynamically finds and loads .class files when they're first needed
Wildcard imports can cause name collisionsDependency management tools like Maven and GradleBuild tools automatically manage which library JARs are available, preventing classpath conflicts at scale
Static imports for utility methodsFramework annotations and dependency injectionFrameworks like Spring use annotations and automatic scanning to wire classes together, going beyond manual imports

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.

Practice Problems

PROBLEM 1 — CONCEPTUAL
Explain why 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?
PROBLEM 2 — BASIC
Write the import statement(s) needed so that the following code compiles. Do NOT use wildcard imports. public class Quiz { public static void main(String[] args) { HashMap<String, Integer> scores = new HashMap<>(); Scanner kb = new Scanner(System.in); } }
PROBLEM 3 — INTERMEDIATE
A student writes the following code and gets a compile error saying "reference to Date is ambiguous." Explain why the error occurs and provide two different ways to fix it. import java.util.*; import java.sql.*; public class Report { Date today = new Date(); }
PROBLEM 4 — APPLIED
You're writing a program that reads numbers from a file, sorts them, and writes statistics. You need 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.
PROBLEM 5 — CRITICAL THINKING
A classmate argues: "Wildcard imports are always better because they're shorter, and they don't affect performance since imports don't load code." Evaluate this argument. Is it entirely correct, partially correct, or wrong? Explain at least two factors the classmate is overlooking.

Lesson 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.

Varsity Tutors • Java • Imports & Qualified Names