Packages & Imports

Reviewed & published by Brayan K

A real Java project has hundreds of classes. Packages are the folders that keep them organised and namespaced, and imports are how one file borrows a class from another. You've used import dozens of times already — now let's understand exactly what it does.

Part of the free Java course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

Before You Start

You should know how to write a class, and it helps to have seen access modifiers — package-private access is defined in terms of packages.

What You'll Learn

The Big Idea — Addresses for Your Classes

💡 Analogy: A package is a postal address for a class. There might be a hundred people called "Smith" in the world, but only one lives at com.shop.model.Smith. The simple name (Product) is the first name; the package (com.shop.model) is the full address. An import is you saving a contact so you can call them by first name instead of reciting their full address every time.

By convention package names use your organisation's reversed domain — com.google.common, org.apache.commons — which guarantees globally unique names. And the package name maps exactly to the folder path: com.shop.model means the file sits in com/shop/model/.

1️⃣ Declaring a Package

The package statement says which package a file belongs to. It must be the first line of code in the file (comments above it are fine), and there can be only one. The file's folder path has to match the package name.

Here's a class declared in a package. Note the very first line:

// File: src/com/shop/model/Product.java
package com.shop.model;          // <-- MUST be the very first line of code

public class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String label() {
        return name + " ($" + price + ")";
    }
}

2️⃣ Importing Classes

To use a class from another package, you import it — then you can refer to it by its short name. Imports go after the package line and before the class. The example below imports your own Product class plus two from the standard library.

3️⃣ Fully Qualified Names

An import is just a shortcut. You can always skip it and write the fully qualified name — the package plus the class — inline. You rarely want to, but there's one case where it's the cleanest solution: when two classes share a simple name (the classic clash is java.util.Date vs java.sql.Date). You can only import one, so you write the other one's full name.

public class Main {
    public static void main(String[] args) {
        // No import? Use the FULLY QUALIFIED NAME instead.
        java.util.List<String> names = new java.util.ArrayList<>();
        names.add("Ada");
        names.add("Grace");
        System.out.println("Names: " + names);

        // This is exactly when you'd reach for a fully qualified name:
        // when two classes share a simple name and you can only import one.
        java.util.Date utilDate = new java.util.Date(0L);
        System.out.println("Epoch: " + utilDate.toInstant());
    }
}

4️⃣ Static Imports

A normal import brings in a class. A import static brings in a class's static members so you can use them without the class prefix. It shines in math-heavy code and test assertions.

import static java.lang.Math.PI;     // now write PI, not Math.PI
import static java.lang.Math.sqrt;   // now write sqrt(x), not Math.sqrt(x)
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
import static java.lang.Math.pow;

public class Main {
    public static void main(String[] args) {
        // Static import lets you drop the "Math." prefix on members.
        double r = 3;
        double area = PI * pow(r, 2);          // instead of Math.PI, Math.pow
        System.out.printf("Circle area: %.2f%n", area);

        double hyp = sqrt(pow(3, 2) + pow(4, 2));
        System.out.println("Hypotenuse of 3,4 triangle: " + hyp);
    }
}

5️⃣ Wildcard Imports

A wildcard import (import java.util.*;) brings in every public class from a package. It has no runtime cost — the compiler only links the classes you actually use — but it hides exactly which classes you depend on, and it can create ambiguity when two wildcards both contain a class with the same simple name. Most teams prefer explicit single imports (and IDEs auto-manage them), but wildcards are common in quick scripts and examples.

import java.util.*;     // import EVERY public class from java.util

public class Main {
    public static void main(String[] args) {
        // All of these come from java.util — one wildcard covers them:
        List<String> list = new ArrayList<>(List.of("c", "a", "b"));
        Collections.sort(list);
        System.out.println("Sorted: " + list);

        Map<String, Integer> ages = new HashMap<>();
        ages.put("Sam", 30);
        System.out.println("Map: " + ages);

        Set<Integer> unique = new TreeSet<>(List.of(3, 1, 3, 2, 1));
        System.out.println("Unique sorted: " + unique);
    }
}

🧩 Reorder Challenge

These are the top lines of a Java source file. Java requires them in a strict order — put them right.

A) import java.util.List;
B) public class Inventory {
C) package com.shop.model;
D) import static java.lang.Math.max;
E) // Inventory of products

Correct order: E, C, A, D, B

// Inventory of products
package com.shop.model;
import java.util.List;
import static java.lang.Math.max;
public class Inventory {

The strict rule: comments may sit anywhere, but the package statement must be the first line of code, then all imports, then the class. Swapping the package and import lines is a compile error.

🧠 Quick Recall

Answer before opening each one.

Answer: ArrayList and Scanner need an import (both from java.util). String and Math live in java.lang, which is imported automatically, so they need no import.

import java.util.List;
package com.app;
public class Main { }

Answer: No. The package statement must come before any import. Here the import is above it, so you get error: class, interface, enum, or record expected / a misplaced-package error. Swap the first two lines.

package com.demo.util;
public class Greeter {
    public static void main(String[] a) {
        System.out.println(Greeter.class.getPackageName());
    }
}

Answer: It prints com.demo.util, and the source file must live at com/demo/util/Greeter.java — the package name maps directly to the folder path.

🎯 Your Turn #1 — Add the missing imports

This file won't compile because its imports are missing. Add the right import lines at the top.

// YOUR TURN: this file uses Scanner and a List but is MISSING its imports.
// Add the two import statements at the top so it compiles.
// Hint: Scanner and ArrayList/List both live in java.util.

public class Main {
    public static void main(String[] args) {
        List<String> words = new ArrayList<>();
        words.add("hello");
        words.add("world");
        System.out.println("Loaded " + words.size() + " words");
        // (Scanner kept here just so you import it too)
        Scanner sc = new Scanner("42");
        System.out.println("Read: " + sc.nextInt());
    }
}

🎯 Your Turn #2 — Switch to static imports

Add static imports for Math.max and Math.min, then simplify the body to drop the Math. prefix.

// YOUR TURN: rewrite the body so it uses a STATIC import of Math.max
// and Math.min instead of writing "Math." each time.
// Add the two static imports at the top, then simplify the lines below.
// Expected output:
//   Bounded 150 to [0,100]: 100
//   Bounded -20 to [0,100]: 0

public class Main {
    public static void main(String[] args) {
        int value = 150;
        int bounded = Math.min(100, Math.max(0, value));
        System.out.println("Bounded 150 to [0,100]: " + bounded);

        value = -20;
        bounded = Math.min(100, Math.max(0, value));
        System.out.println("Bounded -20 to [0,100]: " + bounded);
    }
}

🧩 Mini-Challenge — Wire up a multi-package project

Write the package and import lines for a class that lives in one package and uses types from two others.

// GOAL: imagine a small project with this structure:
//
//   com.bank.model.Account        (a class with a balance)
//   com.bank.service.Transfer     (moves money between two Accounts)
//   com.bank.Main                 (wires it together)
//
// Write the package + import lines for Transfer.java so that it can:
//   1. declare itself in the com.bank.service package
//   2. use Account from com.bank.model
//   3. use List from java.util
//
// Then sketch what Main.java would need to import to use Transfer.
//
// (No runnable output — this is a structure exercise. Compare with the
//  solution below once you've written your version.)

package /* ??? */;
import /* ??? */;
import /* ??? */;

public class Transfer {
    // ...
}

Common Errors

Pro Tips

📋 Quick Reference

TaskSyntaxNotes
Declare packagepackage com.shop.model;First line of code, lowercase
Import one classimport java.util.List;Preferred style
Import a packageimport java.util.*;No runtime cost; less explicit
Static importimport static java.lang.Math.PI;Use a member without its class
Fully qualified namejava.util.Date d;No import; resolves name clashes
Auto-importedjava.lang.*String, System, Math, Integer...

🎉 Lesson Complete!

You now understand how packages namespace and organise classes, how the package name maps to the folder path, and the full toolbox of imports — single, wildcard, static, and fully qualified names — plus why java.lang needs none. That's the skeleton every real Java project hangs on.

Practice quiz

Where must the 'package' statement appear in a Java source file?

  • Anywhere in the file
  • After the imports
  • As the first line of code (comments above it are fine)
  • Inside the class body

Answer: As the first line of code (comments above it are fine). The package declaration must be the first line of code, before any imports, and there can be only one.

How does the package name relate to the folder path?

  • com.shop.model maps to the folder com/shop/model/
  • They are unrelated
  • The folder is always 'src'
  • Only the last segment matters

Answer: com.shop.model maps to the folder com/shop/model/. The package name maps exactly to the directory path: com.shop.model means the file lives in com/shop/model/.

What does an import statement actually let you do?

  • Copy the class into your file
  • Speed up the program at runtime
  • Declare your own package
  • Refer to a class from another package by its short name

Answer: Refer to a class from another package by its short name. An import is a shortcut so you can use a class's simple name instead of its fully qualified name.

Which package is imported automatically into every Java file?

  • java.util
  • java.lang
  • java.io
  • java.time

Answer: java.lang. java.lang is auto-imported, which is why String, System, Math, and Integer need no import.

Which of these needs an explicit import?

  • Scanner
  • String
  • Math
  • System

Answer: Scanner. Scanner lives in java.util and needs an import. String, Math, and System are in java.lang.

What does 'import static java.lang.Math.PI;' allow?

  • Importing the whole Math class
  • Making PI mutable
  • Writing PI instead of Math.PI
  • Importing every static member of Math

Answer: Writing PI instead of Math.PI. A static import brings in a class's static members so you can use them without the class prefix, e.g. PI or sqrt(x).

What is true about a wildcard import like 'import java.util.*;'?

  • It slows the program at runtime
  • It has no runtime cost; the compiler only links classes you use
  • It also imports java.util.concurrent
  • It imports your own package

Answer: It has no runtime cost; the compiler only links classes you use. A wildcard has zero runtime cost. It does NOT reach sub-packages, and it can cause ambiguity for clashing simple names.

When is a fully qualified name (e.g. java.util.Date) most useful?

  • Always, instead of imports
  • Only in the main method
  • Never — it is a syntax error
  • When two classes share a simple name and you can only import one

Answer: When two classes share a simple name and you can only import one. When two classes (like java.util.Date and java.sql.Date) clash, you import one and use the other's full name inline.

What is the correct order of the top lines of a source file?

  • imports, then package, then class
  • package, then imports, then class
  • class, then package, then imports
  • package and imports can be in any order

Answer: package, then imports, then class. It is strictly: (optional comments), package, imports, then the class. Putting an import above package is a compile error.

Does 'import java.util.*;' include classes from java.util.concurrent?

  • Yes, it includes all sub-packages
  • Only at runtime
  • No, a wildcard does not reach sub-packages
  • Only if you also import java.lang

Answer: No, a wildcard does not reach sub-packages. A wildcard covers only the named package, not sub-packages. You must import java.util.concurrent separately.

Continue this course

Frequently asked questions

What is a package and why use one?

A package is a namespace that groups related classes — like a folder for your code. It does three jobs: it prevents name clashes (two classes can both be called Util if they're in different packages), it controls access (package-private members are shared within a package), and it organises a large codebase so related types live together. The package name maps directly to a folder path: com.shop.model lives in com/shop/model/.

What is the difference between a package declaration and an import?

A package declaration (package com.shop.model;) says where THIS file lives — it must be the first line of code in the file, and there can be only one. An import (import java.util.List;) pulls in a class from ANOTHER package so you can use its short name. You declare your own package once; you import as many other classes as you need.

Is a wildcard import like java.util.* slower or bad practice?

It has zero runtime cost — the compiler only pulls in the classes you actually use, so the .class file is identical either way. The objection is purely about clarity: a wildcard hides exactly which classes you depend on and can cause ambiguity if two packages export the same simple name (for example java.util.Date vs java.sql.Date). Most style guides and IDEs prefer explicit single imports, but a wildcard is not 'wrong'.

Why don't I need to import String, System, or Math?

Those live in java.lang, the one package Java imports automatically into every file. String, System, Math, Integer, Object, Thread, and the other core types are all there. Everything outside java.lang — collections (java.util), files (java.io), dates (java.time) — needs an explicit import or a fully qualified name.

What is a static import?

A normal import brings in a class; a static import brings in a class's static members so you can use them without the class prefix. import static java.lang.Math.PI; lets you write PI instead of Math.PI, and import static java.lang.Math.sqrt; lets you call sqrt(x) directly. It's handy for math-heavy code and for test assertions (assertEquals(...)), but overusing it hides where names come from, so use it sparingly.

Related lessons