Java Tutorial
🔍

Java import Statement

Java import Statement

Every time you use ArrayList, HashMap, or LocalDate in Java without writing the full java.util.ArrayList every single time, the import statement is doing that work for you. Without imports, every reference to any class outside java.lang would require the full package path — java.util.ArrayList<java.util.HashMap<java.lang.String, java.util.List<java.lang.Integer>>> instead of ArrayList<HashMap<String, List<Integer>>>.

The import statement tells the compiler where to find a class by its simple name. It does not load the class into memory or make the program heavier — it is purely a compile-time instruction that resolves a short name to a fully qualified one.

How import Works

Without import — full class name required everywhere:
  java.util.ArrayList<String> list = new java.util.ArrayList<>();
  java.util.Collections.sort(list);

With import — short name works:
  import java.util.ArrayList;
  import java.util.Collections;

  ArrayList<String> list = new ArrayList<>();
  Collections.sort(list);

What the import statement does:
  ─ Tells the compiler: "when you see ArrayList, look in java.util"
  ─ Does NOT copy any code or load any class at compile time
  ─ Does NOT affect bytecode or runtime performance
  ─ Does NOT make the JAR file larger
  ─ Is purely a compile-time name-resolution instruction

1 — Single-Type Import (Specific Import)

A single-type import imports exactly one class. This is the recommended style — it makes every dependency explicit and readable at a glance.

1// File: SingleTypeImportDemo.java 2 3package com.devstackflow.demo; 4 5// Each import names exactly one class 6import java.util.ArrayList; 7import java.util.HashMap; 8import java.util.List; 9import java.util.Map; 10import java.util.Collections; 11import java.time.LocalDate; 12import java.time.format.DateTimeFormatter; 13import java.math.BigDecimal; 14 15public class SingleTypeImportDemo { 16 17 public static void main(String[] args) { 18 19 // All imported classes available by simple name 20 List<String> cities = new ArrayList<>(); 21 cities.add("Mumbai"); 22 cities.add("Delhi"); 23 cities.add("Bengaluru"); 24 Collections.sort(cities); 25 System.out.println("Cities : " + cities); 26 27 Map<String, Integer> population = new HashMap<>(); 28 population.put("Mumbai", 20_000_000); 29 population.put("Delhi", 32_000_000); 30 population.put("Bengaluru", 13_000_000); 31 System.out.println("Population : " + population); 32 33 LocalDate today = LocalDate.now(); 34 DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd-MMM-yyyy"); 35 System.out.println("Today : " + today.format(fmt)); 36 37 BigDecimal price = new BigDecimal("4999.99"); 38 System.out.println("Price : Rs." + price); 39 } 40}
Output:
Cities      : [Bengaluru, Delhi, Mumbai]
Population  : {Mumbai=20000000, Delhi=32000000, Bengaluru=13000000}
Today       : 15-Jan-2024
Price       : Rs.4999.99

Specific imports are preferred in professional code because any developer reading the file can immediately see which classes are used — without having to look up what * pulled in.

2 — Wildcard Import

A wildcard import — import package.*; — imports all public classes in a package with one statement. It does not import sub-packages or package-private classes.

1// File: WildcardImportDemo.java 2 3package com.devstackflow.demo; 4 5// Wildcard — imports all public classes in java.util 6import java.util.*; 7 8// Sub-packages are NOT included — must import separately 9import java.util.stream.*; 10import java.util.concurrent.*; 11 12public class WildcardImportDemo { 13 14 public static void main(String[] args) { 15 16 // All java.util classes available 17 List<String> names = new ArrayList<>(List.of("Priya", "Rohan", "Sneha")); 18 Map<String, Integer> scores = new HashMap<>(); 19 scores.put("Priya", 95); 20 scores.put("Rohan", 88); 21 scores.put("Sneha", 92); 22 23 Optional<String> topScorer = scores.entrySet().stream() 24 .max(Map.Entry.comparingByValue()) 25 .map(Map.Entry::getKey); 26 27 System.out.println("Names : " + names); 28 System.out.println("Scores : " + scores); 29 System.out.println("Top scorer : " + topScorer.orElse("none")); 30 31 System.out.println(); 32 33 // java.util.stream was imported separately — not included in java.util.* 34 Stream<String> upperNames = names.stream() 35 .map(String::toUpperCase); 36 System.out.println("Uppercased : "); 37 upperNames.forEach(n -> System.out.println(" " + n)); 38 39 System.out.println(); 40 41 // java.util.concurrent was imported separately 42 ExecutorService executor = Executors.newFixedThreadPool(2); 43 executor.submit(() -> System.out.println("Task from thread pool")); 44 executor.shutdown(); 45 } 46}
Output:
Names      : [Priya, Rohan, Sneha]
Scores     : {Priya=95, Rohan=88, Sneha=92}
Top scorer : Priya

Uppercased :
  PRIYA
  ROHAN
  SNEHA

Task from thread pool

The wildcard * is convenient for exploration but most style guides — Google Java Style Guide, Oracle Coding Conventions — prefer specific imports. IDEs like IntelliJ IDEA automatically expand wildcards to specific imports on save.

Specific Import vs Wildcard Import — Comparison Table

AspectSpecific Import import java.util.ArrayListWildcard Import import java.util.*
ReadabilityHigh — every dependency visible at topLower — unclear which classes are used
Compile timeNo measurable differenceNo measurable difference
Runtime performanceIdentical — both are compile-time onlyIdentical
Risk of name conflictLow — explicit class chosenHigher — two packages may contribute same name
Sub-packages includedN/ANo — java.util.* does not include java.util.stream.*
IDE behaviourPreferred — auto-organised by IDEIDE warns or auto-expands to specific
Style guidesRecommendedDiscouraged in production code
When appropriateAlways in production codeQuick prototyping, exam code

3 — Static Import

import static imports a specific static member — field or method — from a class so it can be used without the class name prefix.

1// File: StaticImportDemo.java 2 3package com.devstackflow.demo; 4 5// Import specific static members 6import static java.lang.Math.PI; 7import static java.lang.Math.sqrt; 8import static java.lang.Math.pow; 9import static java.lang.Math.abs; 10 11// Import all static members of a class 12import static java.util.Collections.sort; 13import static java.util.Collections.reverse; 14import static java.util.Collections.unmodifiableList; 15 16// Import constant from custom class 17import static com.devstackflow.demo.AppConstants.MAX_RETRIES; 18import static com.devstackflow.demo.AppConstants.DEFAULT_TIMEOUT; 19 20import java.util.ArrayList; 21import java.util.Arrays; 22import java.util.List; 23 24class AppConstants { 25 public static final int MAX_RETRIES = 3; 26 public static final long DEFAULT_TIMEOUT = 5000L; 27 public static final String APP_NAME = "DevStackFlow"; 28} 29 30public class StaticImportDemo { 31 32 public static void main(String[] args) { 33 34 // Math methods without "Math." prefix 35 double radius = 7.0; 36 double area = PI * pow(radius, 2); 37 double perimeter = 2 * PI * radius; 38 double diagonal = sqrt(pow(5, 2) + pow(12, 2)); 39 40 System.out.printf("Circle radius : %.1f%n", radius); 41 System.out.printf("Circle area : %.2f%n", area); 42 System.out.printf("Circumference : %.2f%n", perimeter); 43 System.out.printf("3-4-5 diagonal : %.2f%n", diagonal); 44 System.out.printf("abs(-42) : %d%n", abs(-42)); 45 46 System.out.println(); 47 48 // Collections methods without "Collections." prefix 49 List<String> products = new ArrayList<>( 50 Arrays.asList("Laptop", "Mouse", "Keyboard", "Monitor", "Headphones")); 51 52 System.out.println("Before sort : " + products); 53 sort(products); 54 System.out.println("After sort : " + products); 55 reverse(products); 56 System.out.println("After reverse : " + products); 57 58 List<String> immutable = unmodifiableList(products); 59 System.out.println("Immutable list : " + immutable); 60 61 System.out.println(); 62 63 // Custom constants without class prefix 64 System.out.println("Max retries : " + MAX_RETRIES); 65 System.out.println("Default timeout : " + DEFAULT_TIMEOUT + "ms"); 66 } 67}
Output:
Circle radius   : 7.0
Circle area     : 153.94
Circumference   : 43.98
3-4-5 diagonal  : 13.00
abs(-42)        : 42

Before sort     : [Laptop, Mouse, Keyboard, Monitor, Headphones]
After sort      : [Headphones, Keyboard, Laptop, Monitor, Mouse]
After reverse   : [Mouse, Monitor, Laptop, Keyboard, Headphones]
Immutable list  : [Mouse, Monitor, Laptop, Keyboard, Headphones]

Max retries     : 3
Default timeout : 5000ms

Static import is most valuable for: Math methods in mathematical code, Assert methods in unit tests (assertEquals, assertTrue), and constants across the codebase. Avoid it when it makes code less clear — sort(list) is readable, but importing unrelated constants with the same name from multiple classes creates confusion.

4 — java.lang — The Auto-Imported Package

java.lang is the only package automatically imported in every Java file. You never need to write import java.lang.String or import java.lang.System.

1// File: AutoImportDemo.java 2 3package com.devstackflow.demo; 4 5// No imports needed for any java.lang class 6// All of the following are automatically available: 7 8public class AutoImportDemo { 9 10 public static void main(String[] args) { 11 12 // java.lang.String — no import needed 13 String message = "Hello, DevStackFlow!"; 14 System.out.println(message.toUpperCase()); 15 16 // java.lang.System — no import needed 17 System.out.println("Java version: " + System.getProperty("java.version")); 18 19 // java.lang.Math — no import needed 20 System.out.println("Max of 5,9 : " + Math.max(5, 9)); 21 System.out.println("PI : " + Math.PI); 22 23 // java.lang.Integer — no import needed 24 int parsed = Integer.parseInt("42"); 25 System.out.println("Parsed : " + parsed); 26 System.out.println("Max int : " + Integer.MAX_VALUE); 27 28 // java.lang.StringBuilder — no import needed 29 StringBuilder sb = new StringBuilder("Hello"); 30 sb.append(", World"); 31 System.out.println("SB result : " + sb); 32 33 // java.lang.Thread — no import needed 34 System.out.println("Thread : " + Thread.currentThread().getName()); 35 36 // java.lang.Object — root of all classes — no import needed 37 Object obj = new Object(); 38 System.out.println("Object hash: " + obj.hashCode()); 39 } 40}
Output:
HELLO, DEVSTACKFLOW!
Java version: 17.0.9
Max of 5,9 : 9
PI         : 3.141592653589793
Parsed     : 42
Max int    : 2147483647
SB result  : Hello, World
Thread     : main
Object hash: 1173230247

5 — Handling Naming Conflicts

When two packages you need both have a class with the same name, you can only import one by simple name. The other must be used with its fully qualified class name.

1// File: NamingConflictDemo.java 2 3package com.devstackflow.demo; 4 5// Both java.util and java.sql have a class named "Date" 6import java.util.Date; 7// import java.sql.Date; ← cannot import both — same simple name 8 9import java.sql.Connection; 10import java.sql.PreparedStatement; 11 12public class NamingConflictDemo { 13 14 public static void main(String[] args) { 15 16 // java.util.Date — can use simple name because it was imported 17 Date utilDate = new Date(); 18 System.out.println("java.util.Date : " + utilDate); 19 20 // java.sql.Date — must use FQCN because it conflicts with the import above 21 java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis()); 22 System.out.println("java.sql.Date : " + sqlDate); 23 24 System.out.println(); 25 26 // Another common conflict — java.util.List and java.awt.List 27 java.util.List<String> utilList = new java.util.ArrayList<>(); 28 utilList.add("item1"); 29 System.out.println("java.util.List : " + utilList); 30 // java.awt.List — if needed, use: java.awt.List awtList = new java.awt.List(); 31 32 System.out.println(); 33 34 // Best approach when conflict is unavoidable: 35 // Import the one you use most, FQCN for the other 36 // OR use FQCNs for both to make the code unambiguous 37 System.out.println("Conflict resolution: import most-used, FQCN for the rest"); 38 } 39}
Output:
java.util.Date  : Mon Jan 15 10:30:00 IST 2024
java.sql.Date   : 2024-01-15
java.util.List  : [item1]

Conflict resolution: import most-used, FQCN for the rest

6 — Import Ordering and Organisation

The standard import order — enforced by tools like Google Java Style Guide, Checkstyle, and IDE formatters — keeps imports consistent across a team.

1// File: ImportOrderDemo.java 2 3package com.devstackflow.demo; 4 5// ── Block 1: java.* imports ────────────────────────── 6import java.math.BigDecimal; 7import java.time.LocalDate; 8import java.time.LocalDateTime; 9import java.util.ArrayList; 10import java.util.HashMap; 11import java.util.List; 12import java.util.Map; 13 14// ── Block 2: javax.* imports ───────────────────────── 15import javax.crypto.Cipher; 16 17// ── Block 3: Third-party library imports ───────────── 18// import org.springframework.stereotype.Service; 19// import com.fasterxml.jackson.databind.ObjectMapper; 20 21// ── Block 4: Internal project imports (same project) ─ 22// import com.devstackflow.model.Student; 23// import com.devstackflow.service.StudentService; 24 25// ── Block 5: Static imports (at the end) ───────────── 26import static java.lang.Math.PI; 27import static java.util.Collections.sort; 28 29public class ImportOrderDemo { 30 31 public static void main(String[] args) { 32 33 // All imports available by simple name 34 List<String> cities = new ArrayList<>(); 35 cities.add("Mumbai"); 36 cities.add("Delhi"); 37 cities.add("Pune"); 38 sort(cities); // static import 39 40 Map<String, BigDecimal> prices = new HashMap<>(); 41 prices.put("Laptop", new BigDecimal("45999.00")); 42 prices.put("Monitor", new BigDecimal("18500.00")); 43 44 LocalDate orderDate = LocalDate.now(); 45 LocalDateTime timestamp = LocalDateTime.now(); 46 47 System.out.println("Cities : " + cities); 48 System.out.println("Prices : " + prices); 49 System.out.println("Order date: " + orderDate); 50 System.out.println("PI : " + PI); 51 } 52}
Output:
Cities    : [Delhi, Mumbai, Pune]
Prices    : {Laptop=45999.00, Monitor=18500.00}
Order date: 2024-01-15
PI        : 3.141592653589793

Most IDEs format imports automatically. In IntelliJ IDEA: Code → Optimize Imports removes unused imports and organises the rest. In VS Code with the Java extension: imports are managed on save.

Real-World Example — Notification Service With Multiple Import Types

The Business Problem

A notification service at a company like Swiggy or Zomato sends order updates via SMS, email, and push notifications. It uses classes from java.util, java.time, java.math, and the project's own packages — demonstrating specific imports, static imports, and FQCN usage when a conflict arises in a realistic setting.

1// File: com/swiggy/notification/model/NotificationEvent.java 2package com.swiggy.notification.model; 3 4import java.time.LocalDateTime; 5import java.time.format.DateTimeFormatter; 6 7public class NotificationEvent { 8 9 public enum Channel { SMS, EMAIL, PUSH } 10 public enum Priority { LOW, NORMAL, HIGH, CRITICAL } 11 12 private final String eventId; 13 private final String userId; 14 private final String orderId; 15 private final String message; 16 private final Channel channel; 17 private final Priority priority; 18 private final LocalDateTime createdAt; 19 20 public NotificationEvent(String eventId, String userId, 21 String orderId, String message, 22 Channel channel, Priority priority) { 23 this.eventId = eventId; 24 this.userId = userId; 25 this.orderId = orderId; 26 this.message = message; 27 this.channel = channel; 28 this.priority = priority; 29 this.createdAt = LocalDateTime.now(); 30 } 31 32 private static final DateTimeFormatter FMT = 33 DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss"); 34 35 public String getEventId() { return eventId; } 36 public String getUserId() { return userId; } 37 public String getOrderId() { return orderId; } 38 public String getMessage() { return message; } 39 public Channel getChannel() { return channel; } 40 public Priority getPriority(){ return priority; } 41 42 @Override 43 public String toString() { 44 return String.format("[%s] User:%s | Order:%s | %s | %s | %s | %s", 45 eventId, userId, orderId, channel, priority, 46 createdAt.format(FMT), message); 47 } 48}
1// File: com/swiggy/notification/util/EventIdGenerator.java 2package com.swiggy.notification.util; 3 4import java.util.concurrent.atomic.AtomicLong; 5 6public class EventIdGenerator { 7 8 private static final AtomicLong counter = new AtomicLong(1); 9 10 public static String generate(String prefix) { 11 return prefix + "-EVT-" + String.format("%05d", counter.getAndIncrement()); 12 } 13}
1// File: com/swiggy/notification/service/NotificationService.java 2package com.swiggy.notification.service; 3 4// java.* specific imports 5import java.math.BigDecimal; 6import java.time.LocalDateTime; 7import java.time.format.DateTimeFormatter; 8import java.util.ArrayList; 9import java.util.Comparator; 10import java.util.List; 11import java.util.Map; 12import java.util.stream.Collectors; 13 14// Internal project imports 15import com.swiggy.notification.model.NotificationEvent; 16import com.swiggy.notification.model.NotificationEvent.Channel; 17import com.swiggy.notification.model.NotificationEvent.Priority; 18import com.swiggy.notification.util.EventIdGenerator; 19 20// Static imports 21import static java.lang.String.format; 22import static java.util.Collections.unmodifiableList; 23 24public class NotificationService { 25 26 private final List<NotificationEvent> eventLog = new ArrayList<>(); 27 28 public NotificationEvent send(String userId, String orderId, 29 String message, 30 Channel channel, Priority priority) { 31 32 String id = EventIdGenerator.generate(channel.name()); 33 NotificationEvent event = new NotificationEvent( 34 id, userId, orderId, message, channel, priority); 35 eventLog.add(event); 36 37 // Static import of String.format used as 'format' 38 String log = format(" [SENT] %-12s → %s | %s", 39 channel, userId, message); 40 System.out.println(log); 41 42 return event; 43 } 44 45 public List<NotificationEvent> getByChannel(Channel channel) { 46 return eventLog.stream() 47 .filter(e -> e.getChannel() == channel) 48 .collect(Collectors.toList()); 49 } 50 51 public List<NotificationEvent> getByPriority(Priority priority) { 52 return eventLog.stream() 53 .filter(e -> e.getPriority() == priority) 54 .sorted(Comparator.comparing(NotificationEvent::getEventId)) 55 .collect(Collectors.toList()); 56 } 57 58 public Map<Channel, Long> getChannelStats() { 59 return eventLog.stream() 60 .collect(Collectors.groupingBy( 61 NotificationEvent::getChannel, 62 Collectors.counting())); 63 } 64 65 public List<NotificationEvent> getAllEvents() { 66 return unmodifiableList(eventLog); // static import 67 } 68}
1// File: com/swiggy/NotificationApp.java 2package com.swiggy; 3 4// Specific imports — each dependency is explicit 5import com.swiggy.notification.model.NotificationEvent; 6import com.swiggy.notification.model.NotificationEvent.Channel; 7import com.swiggy.notification.model.NotificationEvent.Priority; 8import com.swiggy.notification.service.NotificationService; 9 10import java.util.List; 11import java.util.Map; 12 13public class NotificationApp { 14 15 public static void main(String[] args) { 16 17 System.out.println("╔══════════════════════════════════════════╗"); 18 System.out.println("║ SWIGGY NOTIFICATION SERVICE DEMO ║"); 19 System.out.println("╚══════════════════════════════════════════╝\n"); 20 21 NotificationService service = new NotificationService(); 22 23 System.out.println("Sending notifications:"); 24 System.out.println("─".repeat(65)); 25 26 service.send("USR-101", "ORD-001", "Order placed! Preparing now.", 27 Channel.SMS, Priority.NORMAL); 28 service.send("USR-102", "ORD-002", "Your food is being prepared.", 29 Channel.PUSH, Priority.NORMAL); 30 service.send("USR-101", "ORD-001", "Rider assigned. Arriving in 25 mins.", 31 Channel.SMS, Priority.HIGH); 32 service.send("USR-103", "ORD-003", "Payment failed. Please retry.", 33 Channel.EMAIL, Priority.CRITICAL); 34 service.send("USR-102", "ORD-002", "Order delivered!", 35 Channel.PUSH, Priority.NORMAL); 36 service.send("USR-103", "ORD-003", "Order cancelled. Refund initiated.", 37 Channel.SMS, Priority.HIGH); 38 39 System.out.println(); 40 41 // Channel statistics 42 System.out.println("Channel stats:"); 43 Map<Channel, Long> stats = service.getChannelStats(); 44 stats.forEach((ch, count) -> 45 System.out.printf(" %-8s : %d event(s)%n", ch, count)); 46 47 System.out.println(); 48 49 // All CRITICAL priority events 50 System.out.println("Critical events:"); 51 List<NotificationEvent> critical = service.getByPriority(Priority.CRITICAL); 52 critical.forEach(e -> System.out.println(" " + e)); 53 54 System.out.println(); 55 56 // All SMS events 57 System.out.println("SMS events:"); 58 service.getByChannel(Channel.SMS) 59 .forEach(e -> System.out.println(" " + e)); 60 } 61}
Output:
╔══════════════════════════════════════════╗
║    SWIGGY NOTIFICATION SERVICE DEMO     ║
╚══════════════════════════════════════════╝

Sending notifications:
─────────────────────────────────────────────────────────────────
  [SENT] SMS          → USR-101 | Order placed! Preparing now.
  [SENT] PUSH         → USR-102 | Your food is being prepared.
  [SENT] SMS          → USR-101 | Rider assigned. Arriving in 25 mins.
  [SENT] EMAIL        → USR-103 | Payment failed. Please retry.
  [SENT] PUSH         → USR-102 | Order delivered!
  [SENT] SMS          → USR-103 | Order cancelled. Refund initiated.

Channel stats:
  SMS      : 3 event(s)
  PUSH     : 2 event(s)
  EMAIL    : 1 event(s)

Critical events:
  [EMAIL-EVT-00004] User:USR-103 | Order:ORD-003 | EMAIL | CRITICAL | 15-Jan-2024 10:30:04 | Payment failed. Please retry.

SMS events:
  [SMS-EVT-00001] User:USR-101 | Order:ORD-001 | SMS | NORMAL | 15-Jan-2024 10:30:01 | Order placed! Preparing now.
  [SMS-EVT-00003] User:USR-101 | Order:ORD-001 | SMS | HIGH | 15-Jan-2024 10:30:03 | Rider assigned. Arriving in 25 mins.
  [SMS-EVT-00006] User:USR-103 | Order:ORD-003 | SMS | HIGH | 15-Jan-2024 10:30:06 | Order cancelled. Refund initiated.

Every import is specific and intentional. NotificationEvent.Channel and NotificationEvent.Priority are imported as nested types. format and unmodifiableList are statically imported for clean readability in the service. No wildcard anywhere.

Best Practices

Use specific imports over wildcards in production code. A specific import on every dependency makes the file self-documenting — any reader instantly knows which external types are used. Wildcards save typing but hide dependencies. Every major style guide — Google, Oracle, Spring — mandates specific imports.

Let the IDE manage imports. Do not type import statements manually. In IntelliJ IDEA, Alt+Enter on a class name adds the import automatically. Ctrl+Alt+O (or Cmd+Alt+O on macOS) removes unused imports and organises the rest. In VS Code, the Java extension does the same on save. Manual import management wastes time and introduces errors.

Reserve static imports for well-understood constants and utility methods. import static java.lang.Math.PI and import static org.junit.jupiter.api.Assertions.assertEquals are idiomatic and universally understood. Avoid statically importing methods whose origin is not obvious — sort(list) is clear from context, but process(data) imported from an obscure utility class makes the code opaque.

Remove unused imports. Unused imports are noise — they suggest dependencies that do not exist. They trigger warnings in tools like Checkstyle, SonarQube, and most IDEs. Most CI pipelines fail on unused import warnings. Keep imports clean — one import per class actually used.

Common Mistakes

Mistake 1 — Wildcard Does Not Cover Sub-packages

1import java.util.*; // imports ArrayList, HashMap, Optional, etc. 2// Does NOT import java.util.stream.Stream 3// Does NOT import java.util.concurrent.ExecutorService 4 5Stream<String> stream = // compile error: cannot find symbol Stream 6 7// Fix — import sub-package separately 8import java.util.stream.Stream; 9import java.util.concurrent.ExecutorService;

Mistake 2 — Importing a Class That Does Not Need Importing

1// java.lang is auto-imported — these are redundant 2import java.lang.String; // redundant — String is always available 3import java.lang.System; // redundant — System is always available 4import java.lang.Math; // redundant — Math is always available 5import java.lang.Integer; // redundant — Integer is always available 6 7// IDEs mark all java.lang imports as "redundant import" 8// Style checkers like Checkstyle flag them as violations

Mistake 3 — Ambiguous Import When Two Packages Have Same Class Name

1import java.util.Date; 2import java.sql.Date; // compile error: Date is already defined 3 4// Fix — import only one, use FQCN for the other 5import java.util.Date; 6 7public class Example { 8 Date utilDate = new Date(); // java.util.Date 9 java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis()); // FQCN 10}

Mistake 4 — Placing Import Before Package Declaration

1import java.util.List; // compile error: import before package declaration 2 3package com.devstackflow; // package must be the first non-comment statement 4 5// Correct order: 6package com.devstackflow; 7import java.util.List; 8public class Example { }

Interview Questions

Q1. What does the import statement do in Java?

The import statement is a compile-time instruction that tells the compiler how to resolve a short class name to its fully qualified name. Without it, every class outside java.lang must be referenced by its full package path — java.util.ArrayList instead of ArrayList. The import does not load any code, does not affect the compiled bytecode, does not make the program slower, and does not increase JAR size. It purely enables short-name usage in source code.

Q2. What is the difference between a specific import and a wildcard import?

A specific import — import java.util.ArrayList — imports exactly one named class. A wildcard import — import java.util.* — imports all public classes directly in the specified package, but not sub-packages or package-private classes. Both produce identical compiled bytecode — the compiler resolves which classes are actually used regardless of how many the wildcard might cover. The practical difference is readability and conflict risk: specific imports make dependencies explicit and reduce the chance of name collision.

Q3. What is a static import and when should you use it?

import static imports a static member — field or method — from a class, allowing it to be used without the class name prefix. import static java.lang.Math.PI lets you write PI instead of Math.PI. Static imports are most appropriate for Math constants and methods in mathematical code, Assert methods in JUnit tests (assertEquals, assertTrue), and widely-used constants from your own codebase. Avoid them when the imported name's origin is not obvious from context — clarity always beats brevity.

Q4. Which package is automatically imported in every Java file?

java.lang is the only package automatically imported without any explicit import statement. This provides String, System, Math, Integer, Long, Double, Boolean, Character, StringBuilder, StringBuffer, Thread, Object, Exception, RuntimeException, and all other core language classes without any declaration. All other packages — including java.util, java.io, and java.time — require explicit imports.

Q5. What happens when two imported packages both contain a class with the same name?

A naming conflict occurs. If you write import java.util.Date; import java.sql.Date;, the compiler reports an error — two imports resolve to the same simple name Date. The solution is to import only the more frequently used class and reference the other by its FQCN wherever it appears. Alternatively, remove both imports and use FQCNs for both throughout the file, which makes the distinction explicit at every usage point.

Q6. Does a wildcard import from java.util also import java.util.stream?

No. A wildcard import only covers the classes directly in the named package — it does not extend to sub-packages. import java.util.* imports ArrayList, HashMap, Collections, Optional, and every other public class directly in java.util, but it does not import java.util.stream.Stream, java.util.stream.Collectors, java.util.concurrent.ExecutorService, or any other class in a sub-package. Each sub-package requires its own import statement.

FAQs

Does the order of import statements matter?

The compiler does not care about import order — it processes all imports regardless of sequence. However, teams enforce a standard ordering through style guides and tools. The typical convention: java.* imports first, then javax.*, then third-party libraries, then internal project imports, with static imports last. IDEs auto-sort imports according to configured rules. Consistent ordering reduces unnecessary diffs in version control when two developers independently add imports to the same file.

Can you import a class from the default package?

No. Classes in the default (unnamed) package cannot be imported by classes in named packages. The import keyword requires a fully qualified name with at least one dot separator, which the default package cannot provide. This is one of the fundamental reasons why the default package must be avoided in any project where code needs to be reused or imported.

What is an unused import and why does it matter?

An unused import is an import statement for a class that is not referenced anywhere in the file. The compiler ignores it — it produces no error and no effect on the program. However, unused imports are considered code smell. They mislead readers into thinking a dependency exists when it does not, they trigger warnings from Checkstyle, PMD, and SpotBugs, and they cause test failures on CI pipelines configured to treat warnings as errors. IDEs show them in grey and provide one-click removal.

Can two classes in the same package import each other?

Classes in the same package do not need to import each other at all — they are always mutually visible without any import. If Order.java and OrderItem.java are both in com.myapp.order, either can use the other by simple name with no import statement. This is one of the practical benefits of grouping related classes into the same package.

Is there a performance difference between importing ten specific classes and using a wildcard that covers them all?

No measurable difference at runtime. Both approaches result in exactly the same compiled bytecode — the import statement is erased during compilation. The only difference is at compile time, where the compiler must scan for classes matching the wildcard, which is slightly slower for very large packages with hundreds of classes. In practice this is completely negligible. The choice between specific and wildcard imports is purely a readability and maintainability decision.

Summary

The import statement is a compile-time shortcut — it resolves simple class names to their fully qualified package paths so that you can write ArrayList instead of java.util.ArrayList throughout the file. It has zero effect on the compiled bytecode, the JAR size, or runtime performance.

Three forms: specific import for one class, wildcard for all public classes in a package (but never sub-packages), and static import for static members. java.lang is the sole automatically imported package.

The practice every professional Java team follows: specific imports always, wildcards never in production code, static imports only for well-understood utilities, and IDE import management to keep things clean and ordered.

What to Read Next