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.
Sir, two teams named their class Student. Which one does Java pick?
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.
And my Scanner error?
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.
What are packages and imports?
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.
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
java.util.java.time.LocalDate.LocalDate.package line. Fine for practice only.-cp).The kinds of import
| Form | Example | Effect |
|---|---|---|
| Single-type import | import 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 import | import static java.lang.Math.sqrt; | Use a static member without the class name |
| No import: full name | java.util.List<String> l; | Always works; useful when two classes share a name |
| Automatic | java.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.
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).
Your own packages
Named after a domain you control, reversed: in.myphatshala.fees, com.shop.orders. All lowercase.
Library packages
Added as JAR files by Maven or Gradle: org.junit, com.google.gson, org.springframework.
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);
}
}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 DateFix: 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.
Building and running a two-package program
Put each class in the folder of its package
Folder names follow the package names exactly, one folder per dot-separated part.src/in/myphatshala/fees/FeeCalc.java src/in/myphatshala/app/App.javaDeclare 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)); } }FeeCalcandmonthlymust bepublic, because App is in a different package (Lesson 6.5).Compile with -d so javac creates the package folders
javac writes each class file under> 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.classout/in the folder path of its package.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 outtells 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 findsout/in/myphatshala/app/App.class.In real projects, a build tool does this
Maven and Gradle use the standard layoutsrc/main/java/<package folders>, compile intotarget/classesorbuild/classes, and package everything into a JAR. IDEs create the folders when you create a package.
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.
Scannerwas imported by name, so javac knows it meansjava.util.Scanner.Stringhas no import line, but every file automatically importsjava.lang.*.Listcomes from the wildcardjava.util.*.Functionlives injava.util.function, which is a different package. The wildcard doesn't reach into sub-packages, so javac can't find it.- With both
java.util.*andjava.sql.*, the nameDatematches two classes. javac reports the ambiguity instead of picking one. - Writing
java.util.Datein full removes all doubt, whatever is imported.
- javac first looks at types declared in this file and single-type imports.
Scanneris found there, so its full name is fixed asjava.util.Scanner. Stringisn't declared here, imported by name, or in the same package, so javac checks the on-demand imports, including the automaticjava.lang.*.Listis found throughjava.util.*. In the class file, only the full internal namejava/util/Listis stored.- No level has a
Functionclass:java.util.*covers onlyjava.utilitself. - Two on-demand imports offer
Dateat the same level, so the name is ambiguous. (A single-type import of one of them would win, because level 1 comes first.) - A fully qualified name skips the lookup entirely. Whatever style you use, the bytecode always contains full names; that's why imports have zero run-time cost.
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.
- -cp out tells the JVM where to start looking. The rest of the command is the class's full name.
- Package to path: the class loader replaces dots with folder separators:
in/myphatshala/app/App.class. - Loaded: it reads the file, checks that the class inside really is
in.myphatshala.app.App, and loads it. - main runs and reaches
FeeCalc.monthly(60000). The class file of App stores the full namein/myphatshala/fees/FeeCalc, thanks to the import. - Second lookup: the same rule finds
out/in/myphatshala/fees/FeeCalc.class. Classes are loaded on first use (Lesson 8.4). - Output: 60000 / 12 = 5000. If any folder name didn't match its package, you'd get
ClassNotFoundExceptionorNoClassDefFoundErrorinstead.
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.
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.
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.
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.
Examples are simplified. Since Java 9, related packages can be grouped into a module (module-info.java) that states which packages it exports.
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);
}
}java.timeandjava.time.temporalTwo separate packages, so two imports.import java.util.List;Single-type imports say exactly which List: neverjava.awt.Listby accident.java.math.BigDecimalUsed once, written in full, no import needed.String,SystemFromjava.lang, available everywhere.
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.
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).
today 2025-03-01, exam 2025-03-20
Exam on 2025-03-20: 19 days left
Approach
- Import
java.time.LocalDatefor the dates. - Import
java.time.temporal.ChronoUnitfor counting days. 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.
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.
0.10 + 0.20
BigDecimal: 0.30 double: 0.30000000000000004
Approach
- A fully qualified name works without an import.
- Create BigDecimals from Strings so the values are exact.
- Compare with
doubleto 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.
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.
DB date 2025-01-26
from DB: 2025-01-26 same instant as java.util.Date: true
Approach
import java.util.Date;makesDatemean java.util.Date.- Write
java.sql.Datein full for the database value. 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.
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.langis 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 withjava -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.
Add the missing import
This program uses ArrayList without an import. Add a single-type import and print the list.
items Tea, Vada
[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);
}
}How it works: without the import, javac reports cannot find symbol: class ArrayList. One line tells it the full name.
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.
2025-08-15
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());
}
}How it works: a fully qualified name always works. It's handy for one-off uses or when two classes share a simple name.
Static import of a constant
Use import static java.lang.Math.PI; to compute the area of a circular stage of radius 7 m.
r = 7
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");
}
}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.
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.
names Riya, Kabir
[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);
}
}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.
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.
text "Asha 249.50", date 2025-02-14
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);
}
}How it works: three packages, three single-type imports. A Scanner can read from a String as well as from the keyboard.
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).
today 2025-04-10; due dates 2025-04-05, 2025-04-20
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);
}
}
}How it works: LocalDate.isBefore compares dates correctly, including month and year boundaries. In production you'd use LocalDate.now().
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.)
two orders
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));
}
}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).
Price list with currency formatting
Format prices in Indian style (lakhs and crores) using java.text.NumberFormat and java.util.Locale.
prices 1250, 125000, 12500000
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));
}
}
}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.
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.Daterepresents a date only (for SQL DATE columns), and itstoString()prints justyyyy-mm-dd. The developer meantjava.util.Date.- For new code, use
java.time:LocalDatefor dates,LocalDateTimeorInstantfor 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.
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, whereclassescontainscom/shop/app/App.class. - Better: package the app as a JAR with a
Main-Classin the manifest and runjava -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”.
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.
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.