Import Statement

Import Statement in Java — Complete Guide

Import Statement

The import statement is Java's way of letting you use a short class name instead of typing its full package path every time. This post covers why it exists, the difference between explicit and implicit imports, the ambiguity problems they can cause, and how Java resolves them.

Why We Need It

Without any import, referencing a class from another package by its short name fails:

class Test {
    public static void main(String... args) {
        ArrayList arr = new ArrayList();
    }
}
    

Compile-time error: cannot find symbol: class ArrayList
location: class Test

One fix is to use the fully qualified name every time:

java.util.ArrayList arr = new java.util.ArrayList();
    

The problem: doing this everywhere makes the code longer and harder to read. The import statement solves that — once imported, you can use the short name directly.

import java.util.ArrayList;

class Test {
    public static void main(String... args) {
        ArrayList arr = new ArrayList();
    }
}
    

In short: the import statement is a typing shortcut.


Case 1 — Types of Import Statements

There are two types of class imports: explicit and implicit.

Explicit vs implicit import diagram

Explicit Class Import

  • Highly recommended — it makes the code's dependencies clear and improves readability.
  • Best suited for large projects, where readability matters most.

Implicit Class Import

  • Not generally recommended — it reduces readability since it's unclear exactly which classes are in use.
  • Best suited for quick, small programs where typing speed matters more than clarity.

Case 2 — Which Import Statements Are Meaningful?

Statement
import java.util.ArrayList;
import java.util.ArrayList.*;
import java.util.*;
import java.util;

Of these, only import java.util.ArrayList; (explicit, targeting a class) and import java.util.*; (implicit, targeting a package) are meaningful. ArrayList.* tries to wildcard-import members of a class, which isn't how normal import works, and a bare import java.util; doesn't name a class or use a wildcard, so it doesn't import anything.


Case 3 — Fully Qualified Names Skip the Import

This compiles fine with no import statement at all, because the fully qualified name is used directly:

class MyObj extends java.rmi.UnicastRemoteObject {
}
    

Note: whenever you use a fully qualified name, you don't need an import statement for that class — and whenever you write an import statement, you don't need to use the fully qualified name.


Case 4 — The Ambiguity Problem

Date exists in both java.util and java.sql. Wildcard-importing both creates a genuine conflict — the same issue can happen with List, which exists in both java.util and java.awt.

import java.util.*;
import java.sql.*;

class Test {
    public static void main(String[] args) {
        Date date = new Date();
    }
}
    

Compile-time error: reference to Date is ambiguous

Case 5 — Resolution Precedence

When resolving a class name, the compiler gives precedence in this order:

  1. Explicit class import
  2. Class present in the current working directory (default package)
  3. Implicit class import
import java.util.Date;
import java.sql.*;

class Test {
    public static void main(String... args) {
        Date d = new Date();
        System.out.print(d.getClass().getName());
    }
}
    

Output: java.util.Date

Here, the explicit import of java.util.Date wins over the implicit java.sql.* import.


Case 6 — Sub-Packages Aren't Included Automatically

Importing a package makes every class and interface in that package available — but not the classes in its sub-packages. To use a class from a sub-package, you need an import statement that reaches down to that sub-package specifically.

Package and sub-package structure

To use the Pattern class (in java.util.regex), which import statement is required?

StatementWorks?
import java.*;No
import java.util.*;No
import java.util.regex.*;Yes — correct
No importNo

Case 7 — Packages Available Without Any Import

Every class and interface in these is available to every Java program automatically:

  • java.lang package
  • The default package (your current working directory)

Case 8 — Import Is a Compile-Time Concept

More imports mean more work for the compiler, so compile time increases slightly — but imports have no effect on runtime (execution) performance.

Case 9 — C's #include vs. Java's import

In C, #include loads all referenced headers at the very start of compilation — a static include.

In Java, no .class file is loaded upfront. A class's .class file is only loaded the first time that class is actually used — a dynamic include, loaded on demand.

Conclusion

The import statement exists purely to save typing — a fully qualified name always works without one, and an import never changes runtime behavior, only what you're allowed to type at compile time. The main things to watch for: explicit imports read better and are worth the extra line in real projects; wildcard (implicit) imports don't reach into sub-packages; and importing two classes that share a name (like Date or List) will force a compile-time ambiguity error unless the compiler's precedence rules resolve it for you.

1 Comments