☕ Java
import
The import statement allows you to use a class, interface, or enum by its simple name rather than its fully qualified name. Without an import, every reference to java.util.ArrayList requires writing the full name java.util.ArrayList. With import java.util.ArrayList, you write simply ArrayList. Imports are a compile-time convenience — they have no effect on performance, do not load classes, and are not present in the compiled bytecode. The compiler uses them only to resolve simple names to fully qualified names.
How import Works
An import statement is a compile-time directive to the Java compiler. When the compiler encounters a simple name like ArrayList in source code, it looks for an import statement that maps that name to a fully qualified class name. If it finds import java.util.ArrayList, it substitutes java.util.ArrayList everywhere ArrayList appears in the file. The bytecode contains only fully qualified names — the import statement disappears entirely after compilation.
This compilation-only nature of imports has important consequences. Imports do not cause classes to be loaded. Adding an import statement does not make the program use more memory or start slower. An unused import has zero runtime cost — it is just a warning that IDEs and style checkers flag for cleanliness. The order of import statements does not matter to the compiler, though convention is to sort them alphabetically within groups.
Two forms of import exist. Single-type imports specify one class exactly: import java.util.ArrayList. Type-import-on-demand (wildcard imports) import all public types from a package: import java.util.*. The wildcard form imports all types from the named package but not from sub-packages. import java.util.* does not import java.util.concurrent.ConcurrentHashMap because java.util.concurrent is a separate package.
When two imports would bring in two classes with the same simple name, the compiler reports an ambiguity error. For example, both java.util and java.sql define Date classes. If you import both (java.util.Date and java.sql.Date or via wildcards), any unqualified reference to Date is ambiguous. The resolution is to use the fully qualified name for one or both classes, letting you keep the simple name for the one you use more often.
Java
// ── Import statement syntax: ─────────────────────────────────────────
package com.example.service;
// Single-type imports — explicit, preferred:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// Wildcard import — imports all types from java.io:
import java.io.*;
public class Example {
// Can use ArrayList, HashMap, List, Map, BufferedReader, etc. by simple name
private List<String> names = new ArrayList<>();
private Map<String, Integer> scores = new HashMap<>();
}
// ── Without import — fully qualified names required: ──────────────────
public class NoImports {
private java.util.List<String> names = new java.util.ArrayList<>();
private java.util.Map<String, Integer> scores = new java.util.HashMap<>();
public void readFile() throws java.io.IOException {
java.io.BufferedReader br =
new java.io.BufferedReader(new java.io.FileReader("data.txt"));
}
}
// ── Ambiguity — two packages define a class with the same name: ────────
import java.util.Date;
import java.sql.Date; // COMPILE ERROR — java.util.Date already imported
// Resolution: import one, use fully qualified for the other:
import java.util.Date; // java.util.Date available as 'Date'
public class DateExample {
Date utilDate = new Date(); // java.util.Date
java.sql.Date sqlDate = new java.sql.Date(0); // fully qualified
}
// ── What wildcard * does NOT include: ─────────────────────────────────
import java.util.*; // imports: ArrayList, HashMap, List, Set, etc.
// does NOT import: java.util.concurrent.ConcurrentHashMap
// does NOT import: java.util.stream.Collectors
// sub-packages are SEPARATE packages — not includedSingle-Type Import vs Wildcard Import
Both single-type imports (import java.util.ArrayList) and wildcard imports (import java.util.*) are valid Java. The compiler treats them identically — both allow using the simple name in the file. But they have different implications for readability, maintainability, and tooling.
Single-type imports make the dependencies of a file explicit at a glance. Reading the import block at the top of a file tells you exactly which external classes the file uses. When two imports conflict, the conflict is caught immediately. When a class is renamed or moved, the broken import is immediately visible. IDEs auto-organise single-type imports and add them automatically as you write code.
Wildcard imports hide which specific classes from a package are used. They are shorter — one line instead of many — and proponents argue they reduce import block clutter. The counter-argument is that they obscure the file's dependencies and can hide namespace conflicts until the conflicting class is actually used.
The Google Java Style Guide, Oracle's own Java code style guide, and most team coding standards recommend single-type imports. The reasoning is clarity and explicitness — you should be able to see what a file depends on without wondering which of the fifty classes in java.util are actually needed. Most IDE auto-import features use single-type imports by default.
The java.lang package is implicitly imported by every Java file — you never need import java.lang.String or import java.lang.System. All public types in java.lang are always available by simple name. This is the only automatic import in Java — all other packages require explicit import statements.
Java
// ── Single-type imports — explicit, recommended: ─────────────────────
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
// Reading the imports, you immediately know this file uses:
// ArrayList, Collections, HashMap, List, Map, Optional, and streams.
// ── Wildcard import — terse but opaque: ───────────────────────────────
import java.util.*;
import java.util.stream.*;
// You cannot tell from imports alone which classes are actually used.
// Could be ArrayList + List, or could be LinkedList + Queue + Deque.
// ── java.lang is always implicitly imported: ──────────────────────────
// No import needed for:
String s = "Hello"; // java.lang.String
Integer i = 42; // java.lang.Integer
System.out.println("Hi"); // java.lang.System
Math.sqrt(16); // java.lang.Math
Thread.sleep(100); // java.lang.Thread
// ── IDE convention — organised import groups: ─────────────────────────
//
// Most projects organise imports in groups, each separated by a blank line:
// 1. java.* standard library
// 2. javax.* and jakarta.* extensions
// 3. Third-party libraries (org.springframework, com.fasterxml, etc.)
// 4. Project-internal packages
import java.io.IOException;
import java.util.List;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.springframework.stereotype.Service;
import com.example.model.Order;
import com.example.repository.OrderRepository;Related Topics in Packages and Access Control
Package Concept
A package in Java is a namespace that groups related classes, interfaces, enums, and annotations into a logical unit. Packages solve three fundamental problems in large software systems: name collision (two classes can have the same simple name if they are in different packages), access control (package-private visibility limits access to the same package), and organisation (related types live together and can be found intuitively). Every Java class belongs to a package — either explicitly declared or the unnamed default package.
Built-in Packages
Java ships with a rich standard library organised into packages under the java and javax namespaces. These built-in packages provide data structures, I/O, networking, concurrency, database access, XML processing, GUI components, and much more. Knowing which package contains which functionality, and understanding the most important classes in the most frequently used packages, is foundational knowledge for every Java developer.
User-defined Packages
User-defined packages are packages you create to organise your own application's classes and interfaces. They follow the same rules as Java's built-in packages — the package declaration must be the first statement in the file, the directory structure must match the package hierarchy, and access modifiers control visibility across package boundaries. Designing a meaningful package structure is a foundational software engineering skill that directly affects how maintainable and navigable a codebase remains as it grows.
Static Import
Static import allows you to access static members — static fields and static methods — of a class by their simple name without qualifying them with the class name. Introduced in Java 5, static import reduces verbosity when a few specific static members are used repeatedly. It is most useful for mathematical constants and functions, assertion methods in tests, and constants. Like regular imports, static imports are a compile-time convenience with no runtime effect.