Packages and imports

Two cities can both have an M.G. Road; the full address tells them apart. Java classes work the same way: java.util.Date and java.sql.Date are different classes with the same short name. Packages give every class a full address, and imports let you use the short name. You'll see how packages map to folders, what import really does (and doesn't do), and how to compile and run a packaged program.

Module 6 · OOP Basics⏱ 19 minBeginner8 practice problems
1 The story

Two classes called Student

The college ERP project has grown. The hostel team wrote a Student class, and so did the library team. When Riya tried to use both in one report, nothing compiled. Meanwhile her own code fails with cannot find symbol: class Scanner.

📁 in/college/ 📁 hostel/Student.java 📁 library/Student.java in.college.hostel.Student in.college.library.Student myphatshala.in
Riya

Sir, two teams named their class Student. Which one does Java pick?

Arjun Sir

Neither has to win. Each team puts its class in a package: in.college.hostel and in.college.library. Their full names are now different, like two M.G. Roads in two cities.

Riya

And my Scanner error?

Arjun Sir

Scanner lives in package java.util. Either write its full name, java.util.Scanner, or add import java.util.Scanner; at the top so the short name works. Only java.lang (String, Math, System…) is imported for you automatically.

2 Definition

What are packages and imports?

Formal definition (write this in exams)

A package is a named group of related classes and interfaces that forms a namespace. It is declared with a package statement as the first statement of a source file, e.g. package in.college.fees;. A class's fully qualified name is its package name plus its simple name (java.util.Scanner). An import declaration lets code refer to a type from another package by its simple name: a single-type import (import java.util.Scanner;) names one type; an on-demand import (import java.util.*;) makes all public types of that package available. The package java.lang is imported automatically. Packages also form the boundary for default (package-private) access.

In simple words

A package is a folder of classes with a unique name. import is a shortcut that says “when I write Scanner, I mean java.util.Scanner”. It copies nothing and loads nothing.

Words you'll meet in this lesson

PackageA namespace for classes, written as dot-separated names: java.util.
Fully qualified namePackage + class: java.time.LocalDate.
Simple nameJust the class name: LocalDate.
Default packageThe unnamed package used when a file has no package line. Fine for practice only.
ClasspathThe list of folders and JAR files where the JVM looks for classes (-cp).
JARA zip file of compiled packages, e.g. a library you add to a project.

The kinds of import

FormExampleEffect
Single-type importimport java.util.Scanner;Use Scanner by its simple name
On-demand (wildcard)import java.util.*;All public types in java.util, not its sub-packages
Static importimport static java.lang.Math.sqrt;Use a static member without the class name
No import: full namejava.util.List<String> l;Always works; useful when two classes share a name
Automaticjava.lang.*String, Math, System, Integer, Thread… need no import

Exam tip: order in a source file: package statement (at most one, first) → import statements → type declarations. import java.util.*; does not import java.util.function.Function: sub-packages are separate packages. Imports have no run-time cost; they only affect how javac reads names.

3 Types and ways to use it

Packages you'll use, and how to name your own

Built-in (JDK) packages

java.lang (core), java.util (collections, Scanner), java.time (dates), java.io/java.nio.file (files), java.math (BigDecimal).

java.*, javax.*

Your own packages

Named after a domain you control, reversed: in.myphatshala.fees, com.shop.orders. All lowercase.

reverse domain

Library packages

Added as JAR files by Maven or Gradle: org.junit, com.google.gson, org.springframework.

from the classpath

Imports, full names and java.lang

import java.time.LocalDate;
import java.util.*;
import static java.lang.Math.max;

public class Main {
    public static void main(String[] args) {
        LocalDate due = LocalDate.of(2025, 7, 15);           // single-type import
        List<String> fees = new ArrayList<>();            // from java.util.*
        fees.add("Tuition");
        java.math.BigDecimal gst = new java.math.BigDecimal("0.18");   // full name, no import
        String s = String.valueOf(max(3, 7));                // String: java.lang; max: static import
        System.out.println(due + " " + fees + " " + gst + " " + s);
    }
}
2025-07-15 [Tuition] 0.18 7

When two classes have the same simple name

// import java.util.*;  import java.sql.*;   then:  Date d;
error: reference to Date is ambiguous
  both class java.sql.Date in java.sql and class java.util.Date in java.util match

// import java.util.Date;  import java.sql.Date;
error: a type with the same simple name is already defined by the single-type-import of Date

Fix: import one of them and write the other's full name, e.g. java.sql.Date sqlDate = …;.

Folder structure must match. A file that starts with package in.college.fees; belongs in in/college/fees/. The compiled .class file goes in the same folder path, and the JVM looks for it there. Getting this wrong gives Could not find or load main class.

4 Step by step

Building and running a two-package program

  1. Put each class in the folder of its package

    src/in/myphatshala/fees/FeeCalc.java
    src/in/myphatshala/app/App.java
    Folder names follow the package names exactly, one folder per dot-separated part.
  2. Declare the package and import what you need

    package in.myphatshala.fees;
    
    public class FeeCalc {
        public static int monthly(int annual) { return annual / 12; }
    }
    package in.myphatshala.app;
    
    import in.myphatshala.fees.FeeCalc;
    
    public class App {
        public static void main(String[] args) {
            System.out.println(FeeCalc.monthly(60000));
        }
    }
    FeeCalc and monthly must be public, because App is in a different package (Lesson 6.5).
  3. Compile with -d so javac creates the package folders

    > javac -d out src/in/myphatshala/fees/FeeCalc.java src/in/myphatshala/app/App.java
    
    out/in/myphatshala/fees/FeeCalc.class
    out/in/myphatshala/app/App.class
    javac writes each class file under out/ in the folder path of its package.
  4. Run with the classpath and the fully qualified name

    > java -cp out in.myphatshala.app.App
    5000
    > java -cp out App
    Error: Could not find or load main class App
    Caused by: java.lang.ClassNotFoundException: App
    -cp out tells the JVM where the package folders start. The class must be named in full: in.myphatshala.app.App. The class loader converts the dots to folders and finds out/in/myphatshala/app/App.class.
  5. In real projects, a build tool does this

    Maven and Gradle use the standard layout src/main/java/<package folders>, compile into target/classes or build/classes, and package everything into a JAR. IDEs create the folders when you create a package.
5 See it happen

How javac turns a short name into a class

Left: the names you write in your code. Right: how javac resolves each one to a fully qualified class, the order it checks, and what ends up in the class file.

Resolving Scanner, String, List and Date 6 steps
What you see import java.util.Scanner; import java.util.*; import java.sql.*; Scanner sc = … String name = … List<String> fees = … Function<…> f = … Date d = … java.util.Date d = … ✓ compiles error: cannot find symbol symbol: class Function error: reference to Date is ambiguous Exact match from a single-type import. No import needed: java.lang is automatic. Found through the java.util.* wildcard. java.util.* doesn't include java.util.function. Two wildcards offer a Date: javac won't guess. A fully qualified name is never ambiguous. myphatshala.in
Behind the screen javac's lookup order for a simple name 1. classes in this file / single-type imports 2. classes in the same package 3. on-demand imports (x.*) and java.lang.* → java/util/Scanner → java/lang/String → java/util/List → java/util/Date stored in the class file's constant pool java.util.Function? no such class sub-packages are separate packages java/util/Date and java/sql/Date two candidates at the same level Found at level 1; the search stops. String isn't local or imported by name → level 3. Found by the wildcard at level 3. Nothing found at any level. A tie at level 3 is an error. No lookup needed for a full name. Imports cost nothing at run time: only full names reach the bytecode. myphatshala.in
6 Real-world use

Packages in real projects

In a real codebase, the package list is the map of the system. New team members read it first.

Watch it with an example: the class loader finds App by its address

You type java -cp out in.myphatshala.app.App. Watch the JVM turn the package name into folders, find each class file, and load FeeCalc from another package only when main first needs it.

From a full class name to a .class file 6 steps
Animated example java -cp out in.myphatshala.app.App 📁 out 📁 in 📁 myphatshala 📁 app App.class 📁 fees FeeCalc.class JVM: loaded classes in.myphatshala.app.App main() running in.myphatshala.fees.FeeCalc prints 5000 start at the classpath root: out dots become folders: in/myphatshala/app App.class found and loaded main calls FeeCalc.monthly(60000) FeeCalc's package → in/myphatshala/fees two packages, one program myphatshala.in

1. Organising a large application

A shopping app might have com.shop.orders, com.shop.payments, com.shop.users. Each package holds the classes for one area; teams own different packages.

Feature→its own package→Easy to find and own
<dependency>gson-2.x.jar

2. Using libraries without clashes

Thousands of libraries can be combined because each uses its own reverse-domain package: com.google.gson can never clash with org.json, even if both have a class called JsonParser.

JAR on classpath→import com.google.gson.Gson→Use it
package-private

3. Hiding internals

Classes without public are visible only inside their package (Lesson 6.5). A package can expose one public service and keep its helpers private to the package.

Other packages→public PaymentService→Helpers stay hidden
java.util.Datejava.sql.Datejava.time.LocalDate

4. Choosing the right class among same names

java.util.List vs java.awt.List, and three kinds of Date. IDE auto-import sometimes picks the wrong one; read the import lines when something behaves strangely.

Same simple name→check the import→Right class

Examples are simplified. Since Java 9, related packages can be grouped into a module (module-info.java) that states which packages it exports.

7 Run the code

A fee reminder using four packages

The online editor runs single files, so this program uses classes from four JDK packages instead of its own package folders.

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        LocalDate today = LocalDate.of(2025, 7, 1);
        LocalDate due = LocalDate.of(2025, 7, 15);
        long days = ChronoUnit.DAYS.between(today, due);

        List<String> reminders = new ArrayList<>();
        reminders.add("Tuition fee due in " + days + " days");
        reminders.add("Hostel fee due on " + due);

        java.math.BigDecimal fee = new java.math.BigDecimal("45000.50");
        System.out.println(reminders);
        System.out.println("Amount: " + fee);
    }
}
[Tuition fee due in 14 days, Hostel fee due on 2025-07-15] Amount: 45000.50
  • java.time and java.time.temporalTwo separate packages, so two imports.
  • import java.util.List;Single-type imports say exactly which List: never java.awt.List by accident.
  • java.math.BigDecimalUsed once, written in full, no import needed.
  • String, SystemFrom java.lang, available everywhere.
8 Line by line

Classes from other packages at run time

At run time packages are just part of each class's full name. Watch objects of java.util.ArrayList and java.time.LocalDate appear on the heap like any other object.

Worked examples: real problems, solved and traced in memory

Three small programs that use classes from several JDK packages. Each one needs the right imports, and one shows how to handle two classes with the same name.

Example 1College · attendance

Days until the exam

Problem statement

Show how many days are left until an exam, using classes from java.time and java.time.temporal (two separate packages).

Input
today 2025-03-01, exam 2025-03-20
Expected output
Exam on 2025-03-20: 19 days left

Approach

  1. Import java.time.LocalDate for the dates.
  2. Import java.time.temporal.ChronoUnit for counting days.
  3. ChronoUnit.DAYS.between(a, b) returns a long.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 2Banking · money

Exact money with BigDecimal, no import

Problem statement

Add Rs 0.10 and Rs 0.20 exactly. Use java.math.BigDecimal written by its full name, without any import line.

Input
0.10 + 0.20
Expected output
BigDecimal: 0.30
double:     0.30000000000000004

Approach

  1. A fully qualified name works without an import.
  2. Create BigDecimals from Strings so the values are exact.
  3. Compare with double to see why this matters (Lesson 2.2).

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 3Data · reports

Two Date classes in one program

Problem statement

A report reads a java.sql.Date from a database row and also needs java.util.Date. Import one and write the other in full, then print both kinds.

Input
DB date 2025-01-26
Expected output
from DB: 2025-01-26
same instant as java.util.Date: true

Approach

  1. import java.util.Date; makes Date mean java.util.Date.
  2. Write java.sql.Date in full for the database value.
  3. java.sql.Date.valueOf("2025-01-26") creates one from text.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

9 Quiz and revision

Check yourself

Quick revision

Lesson 6.6 in one screen

  • A package is a namespace for classes; full name = package + class (java.util.Scanner).
  • File order: package → imports → classes. Folders must match package names.
  • Single-type import, wildcard import (one package only, no sub-packages), static import, or the full name.
  • java.lang is imported automatically. Imports have no run-time cost.
  • Same simple name from two packages → import one, write the other in full.
  • Compile with javac -d out …; run with java -cp out pkg.Main.
  • Name packages by reverse domain, lowercase. Packages are also the boundary for default access.

Interview and viva questions

What is a package and why do we use packages?

A namespace that groups related classes. Packages prevent name clashes (two Student classes can coexist), organise large codebases, control access through package-private visibility, and map neatly to folders and JAR files.

What is the difference between import java.util.*; and import java.util.ArrayList;?

The first makes every public type in java.util usable by simple name; the second only ArrayList. They compile to the same bytecode. Single-type imports are clearer and avoid ambiguity, so most style guides and IDEs prefer them.

Does importing a package import its sub-packages?

No. Java has no package hierarchy for imports: java.util and java.util.function are unrelated packages that just share a prefix.

What is a static import? When would you avoid it?

import static java.lang.Math.*; lets you write sqrt(x) instead of Math.sqrt(x). It's handy for constants and test assertions, but overusing it makes it hard to tell where a method comes from.

Why do we get “Could not find or load main class”?

Usually the JVM was given the wrong name or classpath: running java App instead of java -cp out in.shop.app.App, a class file not in the folder matching its package, or a typo in the name. The class loader turns the full name into a path and looks for that file on the classpath.

Practice problems

Fix missing and clashing imports, and practise using classes from several packages. The last three are business tasks.

P1Easy

Add the missing import

This program uses ArrayList without an import. Add a single-type import and print the list.

Input
items Tea, Vada
Expected output
[Tea, Vada]
Show solution and explanation
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> menu = new ArrayList<>();
        menu.add("Tea");
        menu.add("Vada");
        System.out.println(menu);
    }
}
[Tea, Vada]

How it works: without the import, javac reports cannot find symbol: class ArrayList. One line tells it the full name.

P2Easy

Full name instead of import

Print today's date pattern for a fixed date using java.time.LocalDate written in full, with no import line.

Input
2025-08-15
Expected output
2025-08-15 is a FRIDAY
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        java.time.LocalDate d = java.time.LocalDate.of(2025, 8, 15);
        System.out.println(d + " is a " + d.getDayOfWeek());
    }
}
2025-08-15 is a FRIDAY

How it works: a fully qualified name always works. It's handy for one-off uses or when two classes share a simple name.

P3Easy

Static import of a constant

Use import static java.lang.Math.PI; to compute the area of a circular stage of radius 7 m.

Input
r = 7
Expected output
154 sq m
Show solution and explanation
import static java.lang.Math.PI;

public class Main {
    public static void main(String[] args) {
        double r = 7;
        double area = PI * r * r;
        System.out.println(Math.round(area) + " sq m");
    }
}
154 sq m

How it works: the static import lets you write PI instead of Math.PI. Math.round is still written with the class name, which is fine.

P4Medium

Fix the ambiguous List

A file has import java.util.*; and import java.awt.*;, both of which have a List. Fix it so List means java.util.List.

Input
names Riya, Kabir
Expected output
[Riya, Kabir]
Show solution and explanation
import java.util.*;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Riya");
        names.add("Kabir");
        System.out.println(names);
    }
}
[Riya, Kabir]

How it works: a single-type import beats wildcards, so List now clearly means java.util.List, even if another wildcard (like java.awt.*) also offers one. Here the AWT import was simply removed because it wasn't needed.

P5Medium

Classes from three packages

Use java.util.Scanner to read a name and amount from a String, java.math.BigDecimal for the amount and java.time.LocalDate for the receipt date.

Input
text "Asha 249.50", date 2025-02-14
Expected output
2025-02-14 | Asha paid Rs 249.50
Show solution and explanation
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner("Asha 249.50");
        String name = sc.next();
        BigDecimal amount = new BigDecimal(sc.next());
        LocalDate date = LocalDate.of(2025, 2, 14);
        System.out.println(date + " | " + name + " paid Rs " + amount);
    }
}
2025-02-14 | Asha paid Rs 249.50

How it works: three packages, three single-type imports. A Scanner can read from a String as well as from the keyboard.

P6Business problem

Due-date checker for invoices

Mark each invoice as "OVERDUE" or "OK" by comparing its due date with today's date (fixed here so the output is repeatable).

Input
today 2025-04-10; due dates 2025-04-05, 2025-04-20
Expected output
INV-101 due 2025-04-05: OVERDUE
INV-102 due 2025-04-20: OK
Show solution and explanation
import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        LocalDate today = LocalDate.of(2025, 4, 10);
        String[] ids = {"INV-101", "INV-102"};
        LocalDate[] due = {LocalDate.of(2025, 4, 5), LocalDate.of(2025, 4, 20)};
        for (int i = 0; i < ids.length; i++) {
            String status = due[i].isBefore(today) ? "OVERDUE" : "OK";
            System.out.println(ids[i] + " due " + due[i] + ": " + status);
        }
    }
}
INV-101 due 2025-04-05: OVERDUE INV-102 due 2025-04-20: OK

How it works: LocalDate.isBefore compares dates correctly, including month and year boundaries. In production you'd use LocalDate.now().

P7Business problem

Unique order IDs with java.util.UUID

Generate an order ID with java.util.UUID and show that two generated IDs are different. (UUIDs are random, so print only their length and whether they differ.)

Input
two orders
Expected output
ID length: 36
Different: true
Show solution and explanation
import java.util.UUID;

public class Main {
    public static void main(String[] args) {
        String a = UUID.randomUUID().toString();
        String b = UUID.randomUUID().toString();
        System.out.println("ID length: " + a.length());
        System.out.println("Different: " + !a.equals(b));
    }
}
ID length: 36 Different: true

How it works: a UUID is a 36-character random identifier, practically unique even across many servers. That's why distributed systems use it instead of a static counter (Lesson 6.4).

P8Business problem

Price list with currency formatting

Format prices in Indian style (lakhs and crores) using java.text.NumberFormat and java.util.Locale.

Input
prices 1250, 125000, 12500000
Expected output
Rs 1,250
Rs 125,000
Rs 12,500,000
Show solution and explanation
import java.text.NumberFormat;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        NumberFormat f = NumberFormat.getNumberInstance(Locale.forLanguageTag("en-IN"));
        long[] prices = {1250, 125000, 12500000};
        for (long p : prices) {
            System.out.println("Rs " + f.format(p));
        }
    }
}
Rs 1,250 Rs 125,000 Rs 12,500,000

How it works: the Indian locale groups digits as 1,25,00,000. Formatting classes live in java.text; locales in java.util.

Real-world scenario questions (asked in company interviews)

Package questions in interviews are usually about build problems and name clashes. Think it through, then open the model answer.

Fintech · bug huntFresher

The wrong Date

A report shows dates without times. The code uses Date, and the import line is import java.sql.Date;, added automatically by the IDE. What's happening?

The interviewer is checking: do you know that the same simple name can mean different classes?

Show a strong answer
  • java.sql.Date represents a date only (for SQL DATE columns), and its toString() prints just yyyy-mm-dd. The developer meant java.util.Date.
  • For new code, use java.time: LocalDate for dates, LocalDateTime or Instant for timestamps.
  • Review import lines in code review; IDE auto-import can pick the wrong class silently.

Avoid: assuming a class name is unique across the JDK.

DevOps · deployment1–3 years

Works in the IDE, fails on the server

The app runs in the IDE, but on the server java App prints Could not find or load main class App. The class starts with package com.shop.app;. How do you fix the command?

The interviewer is checking: do you understand classpath and fully qualified names?

Show a strong answer
  • The JVM needs the fully qualified name and the classpath root: java -cp classes com.shop.app.App, where classes contains com/shop/app/App.class.
  • Better: package the app as a JAR with a Main-Class in the manifest and run java -jar shop.jar; include dependencies via the build tool.
  • The IDE worked because it builds the classpath for you.

Avoid: moving the class out of its package to “make it work”.

Code review · styleFresher

Wildcard imports: yes or no?

A reviewer asks you to replace import java.util.*; with explicit imports. You say wildcards are faster to write and don't affect performance. Who's right?

The interviewer is checking: do you know the real trade-off?

Show a strong answer
  • You're right that there's no run-time difference; the bytecode is identical.
  • The reviewer is right about readability and safety: explicit imports show exactly which classes are used, and a new class added to a wildcard-imported package can create an ambiguity later.
  • Follow the team's style guide; IDEs can manage explicit imports automatically.

Avoid: claiming wildcards load the whole package into memory.

Architecture · large codebase3+ years

Package by layer or by feature?

A growing e-commerce codebase has packages controllers, services, repositories, each with 200 classes. Changes to “orders” touch all three. Someone suggests packaging by feature instead. Your view?

The interviewer is checking: can you use packages as a design tool?

Show a strong answer
  • Package by feature (orders, payments, users) keeps related classes together, so a change usually stays within one package.
  • Within a feature package, only the entry points need to be public; helpers can be package-private, which the layered layout can't do.
  • Migrate gradually, starting with the most-changed feature.

Avoid: treating packages as just folders with no effect on design.