Java Module 5 – Classes, objects, records and enums
Packages, imports and the class path
Put Java classes in packages that match their folders, use single-type, on-demand, static and module imports, and run programs with javac -d and java -cp.
What you will learn
- Organise classes into packages whose folders match their names, and run a class by its full name
- Use single-type, on-demand, static and module imports
- Resolve a simple name that two imports offer
- Predict where java looks for a class on a class path of folders and JAR files
- Diagnose a NoClassDefFoundError caused by a class path that differs between compiling and running
Before you start
What you’ll learn · Before you start
What you will learn
- Organise classes into packages whose folders match their names, and run a class by its full name
- Use single-type, on-demand, static and module imports
- Resolve a simple name that two imports offer
- Predict where java looks for a class on a class path of folders and JAR files
- Diagnose a NoClassDefFoundError caused by a class path that differs between compiling and running
Before you start
On this page
javac -d out wrote Main.class into out/com/example/library/app/, and java -cp out Main still fails: a class
in a package is found only by its full name, one folder for each part of it. A package: A named group of classes, such as com.example.shop, declared on the first line of a source file. javac -d stores its class files in folders that follow the name, and java runs such a class by its full name. More in “Classic main, javac and .class files” is
a named group of classes, declared with a first line such as package com.example.library.model;, and it maps onto
those folders. An import lets code use a class from another package by its simple name, Book instead of
com.example.library.model.Book.
The class path: The folders and JAR files in which the JVM looks for classes, given with -cp or --class-path. Without it, and without a CLASSPATH environment variable, it is the current folder. More in “Classic main, javac and .class files” is the list of folders and JAR files where java looks for compiled
classes. This lesson builds a small two-package program, compiles and runs it the right way and two wrong ways,
settles which Date a file gets when two imports offer one, and packs one package into a JAR to show what the class
path does at run time. The commands below ran on the JDK of Eclipse Temurin 25.0.4.1, a Java 25 release.
A package name is a path of folders
The program has two packages. com.example.library.model holds the data, Book and Catalogue, and
com.example.library.app holds the program, Main. The names follow the convention of JLS 6.1: start from a domain
name you control, reversed, here example.com, a domain reserved for examples (RFC 2606), so that two
organisations never choose the same package name.
library/src/com/example/library/app/Main.java
package com.example.library.app;
import com.example.library.model.Book;
import com.example.library.model.Catalogue;
public class Main {
public static void main(String[] args) {
Catalogue catalogue = new Catalogue();
catalogue.add(new Book("Gitanjali", "Rabindranath Tagore", 3));
catalogue.add(new Book("Godaan", "Premchand", 2));
IO.println(catalogue.size() + " titles, " + catalogue.copiesOf("Godaan") + " copies of Godaan");
IO.println("this class is " + Main.class.getName());
}
} library/src/com/example/library/model/Book.java
package com.example.library.model;
/** A title in the catalogue and how many copies the library owns. */
public record Book(String title, String author, int copies) {} library/src/com/example/library/model/Catalogue.java
package com.example.library.model;
import java.util.ArrayList;
import java.util.List;
/** The library's books. Code in other packages sees only the public methods. */
public class Catalogue {
private final List<Book> books = new ArrayList<>();
public void add(Book book) {
books.add(book);
}
public int copiesOf(String title) {
int copies = 0;
for (Book book : books) {
if (book.title().equals(title)) {
copies += book.copies();
}
}
return copies;
}
public int size() {
return books.size();
}
} from session import run
# Compile the three files into out, then run the class by its full name; then two ways to get it wrong,
# and the source launcher, which works out the source root from the package.
run(
"""
find library/src -name "*.java" | sort
javac -d out $(find library/src -name "*.java")
find out -name "*.class" | sort
java -cp out com.example.library.app.Main
java -cp out Main
java com.example.library.app.Main
java library/src/com/example/library/app/Main.java
""",
fails=("java -cp out Main", "java com.example.library.app.Main"),
) Output
# openjdk version "25.0.4.1" LTS $ find library/src -name "*.java" | sort library/src/com/example/library/app/Main.java library/src/com/example/library/model/Book.java library/src/com/example/library/model/Catalogue.java $ javac -d out $(find library/src -name "*.java") $ find out -name "*.class" | sort out/com/example/library/app/Main.class out/com/example/library/model/Book.class out/com/example/library/model/Catalogue.class $ java -cp out com.example.library.app.Main 2 titles, 2 copies of Godaan this class is com.example.library.app.Main $ java -cp out Main Error: Could not find or load main class Main Caused by: java.lang.ClassNotFoundException: Main [exit status 1] $ java com.example.library.app.Main Error: Could not find or load main class com.example.library.app.Main Caused by: java.lang.ClassNotFoundException: com.example.library.app.Main [exit status 1] $ java library/src/com/example/library/app/Main.java 2 titles, 2 copies of Godaan this class is com.example.library.app.Main
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 packages_session.py
Step through the session: the folders the files live in are on the left, and each command on the right either finds its class by the folders or does not:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- One folder per part. Each part of the package name is one folder below the source root library/src: com/example/library/app holds Main.java, and com/example/library/model holds Book.java and Catalogue.java.
- javac -d out. javac -d out writes each class file into the same folders below out, creating them as needed: out/com/example/library/app/Main.class and the two model classes.
- Run by the full name. java -cp out com.example.library.app.Main turns the full name into the path com/example/library/app/Main.class below out, finds it and runs: 2 titles, 2 copies of Godaan.
- The simple name fails. java -cp out Main looks for out/Main.class. No class is called just Main, so the run stops: Could not find or load main class Main.
- No class path given. java com.example.library.app.Main, with no -cp and no CLASSPATH variable, searches only the current folder, which has no com folder, so it fails the same way.
- The source launcher. java library/src/com/example/library/app/Main.java reads the file's package, works out that library/src is the source root, and compiles the model classes from there. It prints the same two lines.
- The source folders follow the packages. Each part of the package name is one folder, below a source root,
here
library/src. JLS 7.2 describes this layout for packages kept in a file system, and javac’s source path, the launcher and build tools such as Maven expect it. javac -d outwrites the same folders. The class files land inout/com/example/library/..., one folder per part of the package name, created as needed. The$(find ...)part is the shell’s way of passing every source file to javac.- Run the class by its full name, with the output folder on the class path.
java -cp out Mainfails, because no class is called justMain. The fully qualified name: A class's name with its package in front, such as com.example.library.model.Book. The JVM turns it into the path com/example/library/model/Book.class, and java runs a class in a package only by this name.,com.example.library.app.Main, is what the JVM turns into a path. With no-cpand noCLASSPATHvariable, the class path is only the current folder, sojava com.example.library.app.Mainlooks for./com/example/library/app/Main.classand finds nothing. - The source launcher works too.
java library/src/com/example/library/app/Main.javaread the file’s package, worked out thatlibrary/srcis the root of the source tree, and compiled the model classes from there (JEP 458).
Two more facts about packages matter in practice. Main used Book because Book is public; a class without a
modifier would be invisible outside its package, as the
encapsulation lesson showed. And packages whose names share a
prefix are not related: code in com.example.library.app has no special access to com.example.library.model (JLS
7.1), and an import of one does not import the other.
When the folder and the package disagree
Nothing forces a file’s package declaration to match the folder it is saved in. Helper.java sits in
com/example/tools/ but declares package com.example.util;:
package com.example.util;
/** Declared in com.example.util, but saved in the folder com/example/tools. */
public class Helper {
public static void main(String[] args) {
IO.println("Helper runs");
}
} from session import run
# javac files the class under its declared package; the source launcher insists that the folders match it.
run(
"""
javac -d out wrong/com/example/tools/Helper.java
find out -name "*.class"
java wrong/com/example/tools/Helper.java
""",
fails=("java wrong/com/example/tools/Helper.java",),
) Output
# openjdk version "25.0.4.1" LTS $ javac -d out wrong/com/example/tools/Helper.java $ find out -name "*.class" out/com/example/util/Helper.class $ java wrong/com/example/tools/Helper.java error: end of path to source file does not match its package name com.example.util: wrong/com/example/tools/Helper.java [exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 mismatch_session.py
Given the file by name, javac compiled it without a word and filed the class under its declared package,
out/com/example/util/. The source launcher refused it, and so would any tool that looks for com.example.util.Helper
in com/example/util/Helper.java, such as javac with --source-path. Keep every file in the folder its package names,
and the question never comes up.
Checkpoint
Check: Packages as folders
An import changes only which simple names a file can use
An import loads nothing and copies nothing: the class file stores full names either way. It only changes which simple
names the compiler understands. Kinds.java uses one import of each kind:
import java.util.List; // a single-type import: one class
import java.time.*; // an on-demand import: every public class of java.time
import static java.lang.Math.max; // a static import: one static member of a class
import module java.net.http; // a module import: every package that java.net.http exports
class Kinds {
static void main() {
List<String> shifts = List.of("morning", "evening");
DayOfWeek reopens = DayOfWeek.FRIDAY.plus(3);
int larger = max(3, 9);
HttpClient.Version version = HttpClient.Version.HTTP_2;
IO.println(shifts + " " + reopens + " " + larger + " " + version);
}
} from session import run
# The four kinds of import in one file, then what two modules export (sorted: the JDK lists a module's
# requirements in no fixed order).
run(
"""
java imports/Kinds.java
java --describe-module java.base | grep -c "^exports "
java --describe-module java.base | grep "^exports java.lang.classfile"
java --describe-module java.sql | sort
"""
) Output
# openjdk version "25.0.4.1" LTS $ java imports/Kinds.java [morning, evening] MONDAY 9 HTTP_2 $ java --describe-module java.base | grep -c "^exports " 58 $ java --describe-module java.base | grep "^exports java.lang.classfile" exports java.lang.classfile exports java.lang.classfile.attribute exports java.lang.classfile.constantpool exports java.lang.classfile.instruction $ java --describe-module java.sql | sort exports java.sql exports javax.sql java.sql@25.0.4.1 requires java.base mandated requires java.logging transitive requires java.transaction.xa transitive requires java.xml transitive uses java.sql.Driver
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 kinds_session.py
| Import | What it makes usable by simple name |
|---|---|
import java.util.List; (single-type import: An import of one class or interface by its full name, such as import java.util.List;. It shadows a class of the same simple name that an on-demand or module import would bring.) |
One class or interface |
import java.time.*; (on-demand import: An import that ends in .*, such as import java.time.*;. It makes every public class and interface of one package usable by its simple name, but not those of its subpackages.) |
Every public class and interface of one package, not of its subpackages |
import static java.lang.Math.max; (static import: An import static declaration, such as import static java.lang.Math.max;. It makes a static member of a class, or with .* all of them, usable without the class name in front.) |
A static member of a class; import static java.lang.Math.*; brings all of them |
import module java.net.http; (module import: An import module declaration, such as import module java.base; (JEP 511). It makes every public class and interface of every package the module exports usable by its simple name. Compact source files import java.base this way., JEP 511) |
Every public class of every package the module exports |
java --describe-module shows what a module offers. On this JDK, java.base exports 58 packages, which is what
every compact source file imports implicitly. JEP 511 gives 54; the difference is the four java.lang.classfile
packages of the Class-File API, a standard API since Java 24 (JEP 484). java.sql exports two packages, java.sql
and javax.sql, and its requires ... transitive lines matter too: import module java.sql; also imports what
java.logging, java.transaction.xa and java.xml export, because code that uses java.sql needs their types.
Expecting java.util.* to cover java.util.function
An on-demand import covers one package. import java.util.*; gives List and Map but not Function, which
lives in java.util.function: import java.util.function.Function too, or use import module java.base;.
Checkpoint
Check: The four kinds of import
When two imports offer one name, the more specific kind wins
java.base exports java.util, which has a Date class, and java.sql has a Date of its own. Three files ask
for Date:
imports/Ambiguous.java
import module java.sql;
void main() {
Date due = new Date(0);
IO.println(due.getClass().getName());
} imports/Resolved.java
import module java.sql;
import java.sql.Date;
void main() {
Date due = new Date(0);
IO.println(due.getClass().getName());
} imports/Silent.java
import java.sql.*;
void main() {
Date due = new Date(0);
IO.println(due.getClass().getName());
} from session import run
# Date is in java.util (exported by java.base) and in java.sql: which one does each file get?
run(
"""
java imports/Ambiguous.java
java imports/Resolved.java
java imports/Silent.java
""",
fails=("java imports/Ambiguous.java",),
) Output
# openjdk version "25.0.4.1" LTS
$ java imports/Ambiguous.java
imports/Ambiguous.java:4: error: reference to Date is ambiguous
Date due = new Date(0);
^
both class java.sql.Date in java.sql and class java.util.Date in java.util match
imports/Ambiguous.java:4: error: reference to Date is ambiguous
Date due = new Date(0);
^
both class java.sql.Date in java.sql and class java.util.Date in java.util match
2 errors
error: compilation failed
[exit status 1]
$ java imports/Resolved.java
java.sql.Date
$ java imports/Silent.java
java.sql.Date
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 ambiguity_session.py
All three are compact source files, so each starts with an implicit import module java.base;. Step through how
javac settles Date in each of them:
The drawing shows the whole scene; its 7 steps are listed below.
Every step as text
- Ambiguous.java: no single-type. Ambiguous.java has no single-type import of Date, so javac looks further down.
- No on-demand import. It has no on-demand import either, only import module java.sql; and the implicit import module java.base;.
- Two modules, two Dates. java.sql exports java.sql, which has a Date, and java.base exports java.util, which has another. Two imports of the same kind offer the name.
- Ambiguous. javac stops with reference to Date is ambiguous, twice: once for the type of due and once for new Date(0).
- Resolved.java. Resolved.java adds import java.sql.Date;. A single-type import shadows on-demand and module imports, so the search stops at the top and the run prints java.sql.Date.
- Silent.java. Silent.java has only import java.sql.*;. An on-demand import shadows module imports, the implicit java.base included, so Date is java.sql.Date with no error and no warning.
- Two on-demand imports. In an ordinary class, import java.util.; with import java.sql.; is ambiguous instead: both imports are on demand, equally specific, and each offers a Date.
- In
Ambiguous.java, two module imports offer aDateeach, so the name is ambiguous and the file does not compile. - In
Resolved.java,import java.sql.Date;settles it. A single-type import shadows the classes of the same name from on-demand and module imports (JLS 6.4.1). Silent.javais the trap. An on-demand import,import java.sql.*;, also shadows module imports, soDatebecamejava.sql.Datewith no error and no warning. In an ordinary class,import java.util.*;withimport java.sql.*;is ambiguous instead, because two on-demand imports are equally specific.
The order of the import lines never matters; only their kinds do. When two packages share a name, import the one you mean by its full name, so the file says which class it uses.
Key idea
A single-type import beats an on-demand import, which beats a module import; two imports of the same kind that offer one name make it ambiguous, and the order of the lines never decides anything.
Checkpoint
Check: Two imports, one name
The class path is searched in order, and the first match wins
The class path is a list of folders and JAR files, separated by : on Linux and macOS and by ; on Windows. A
JAR file: A ZIP archive of class files kept in their package folders, with a manifest in META-INF/MANIFEST.MF. Put on the class path, it is searched for classes like a folder. is a ZIP archive of class files, laid out in the same package folders. To find a
class, the JVM turns its name into a path, com/example/library/model/Book.class, and searches the entries in
order, using the first one that has it:
How the class path finds a class
Text description of the diagram
The diagram shows how java -cp app-out:library-model.jar com.example.library.app.Main finds the class com.example.library.model.Book.
- The class name com.example.library.model.Book becomes the relative path com/example/library/model/Book.class: one folder per part of the package name.
- The first class path entry, the folder app-out, is searched for that path.
- If it is not there, the second entry, the JAR file library-model.jar, is searched for the same path inside the JAR.
- The class is loaded from the first entry that has it, so the order of the entries matters when two of them contain the same class.
- If no entry has it, loading fails: with ClassNotFoundException when the class was asked for by name, such as the main class, or with NoClassDefFoundError when compiled code needs a class that is missing at run time.
-cp (also spelled --class-path or -classpath) sets the list for one command and overrides the CLASSPATH
environment variable; with neither, the class path is just the current folder. A class path entry ending in *, such
as lib/*, stands for every JAR file in that folder. Because the first entry that has a class wins, the order of the
entries matters whenever two of them contain the same class.
Checkpoint
Check: How the class path is searched
A class that was there at compile time can be missing at run time
Here the model package goes into a JAR, Main is compiled against it, and then run with and without it:
from session import run
# The model classes go into a JAR file; the app is compiled against it, run with it, and run without it.
run(
"""
javac -d model-out library/src/com/example/library/model/*.java
jar --create --file library-model.jar -C model-out .
jar --list --file library-model.jar
javac -d app-out -cp library-model.jar library/src/com/example/library/app/Main.java
java -cp app-out:library-model.jar com.example.library.app.Main
java -cp app-out com.example.library.app.Main
""",
fails=("java -cp app-out com.example.library.app.Main",),
) Output
# openjdk version "25.0.4.1" LTS $ javac -d model-out library/src/com/example/library/model/*.java $ jar --create --file library-model.jar -C model-out . $ jar --list --file library-model.jar META-INF/ META-INF/MANIFEST.MF com/ com/example/ com/example/library/ com/example/library/model/ com/example/library/model/Book.class com/example/library/model/Catalogue.class $ javac -d app-out -cp library-model.jar library/src/com/example/library/app/Main.java $ java -cp app-out:library-model.jar com.example.library.app.Main 2 titles, 2 copies of Godaan this class is com.example.library.app.Main $ java -cp app-out com.example.library.app.Main Exception in thread "main" java.lang.NoClassDefFoundError: com/example/library/model/Catalogue at com.example.library.app.Main.main(Main.java:8) Caused by: java.lang.ClassNotFoundException: com.example.library.model.Catalogue at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490) ... 1 more [exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 classpath_session.py
Step through the same commands and watch where each class Main needs is found:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- Build the JAR. javac compiles the model package into model-out, and jar --create packs it into library-model.jar. jar --list shows that the JAR keeps the package folders, com/example/library/model/Book.class included.
- Compile against it. javac -cp library-model.jar compiles Main into app-out. Main.class records the names of Book and Catalogue, not where they were found.
- Run with both entries. java -cp app-out:library-model.jar searches app-out first and finds Main there. When line 8 needs Catalogue, app-out has no such path, and the JAR has it.
- It runs. Book comes from the JAR as well, and the run prints 2 titles, 2 copies of Godaan, then this class is com.example.library.app.Main.
- Run without the JAR. java -cp app-out leaves the JAR out. Main is still found in app-out, so the program starts.
- Line 8 fails. At line 8 the JVM needs Catalogue and finds it in no entry: NoClassDefFoundError, caused by ClassNotFoundException. The class existed when Main was compiled, and is missing now.
jar --list shows that the JAR keeps the package folders, so the same lookup works inside it. Without the JAR on the
class path, Main still started, because its own class was found in app-out, and failed at line 8, the first line
that needs Catalogue, with NoClassDefFoundError. That error means the class existed when the code was compiled
but cannot be found now. For a missing JAR, the fix is on the command line or in the build’s dependencies, not in the
code.
Checkpoint
Check: A class missing at run time
Practise: fix a broken two-package project
Here is a small shop program with mistakes of three kinds that this lesson covered, compiled as it is:
practice/src/com/example/shop/app/Checkout.java
package com.example.shop;
import com.example.shop.cart.Item;
public class Checkout {
public static void main(String[] args) {
Cart cart = new Cart();
cart.add(new Item("notebook", 4_500, 2));
cart.add(new Item("pen", 1_000, 3));
IO.println(cart.count() + " items, total " + cart.totalPaise() + " paise");
}
} practice/src/com/example/shop/cart/Cart.java
package com.example.shop.cart;
class Cart {
private final List<Item> items = new ArrayList<>();
public void add(Item item) {
items.add(item);
}
public int count() {
return items.size();
}
public long totalPaise() {
long total = 0;
for (Item item : items) {
total += item.totalPaise();
}
return total;
}
} practice/src/com/example/shop/cart/Item.java
public record Item(String name, long pricePaise, int quantity) {
public long totalPaise() {
return pricePaise * quantity;
}
} from session import run
# The broken project, compiled as it is.
run('javac -d out $(find practice/src -name "*.java" | sort)', fails=('javac -d out $(find practice/src -name "*.java" | sort)',)) Output
# openjdk version "25.0.4.1" LTS
$ javac -d out $(find practice/src -name "*.java" | sort)
practice/src/com/example/shop/app/Checkout.java:3: error: cannot find symbol
import com.example.shop.cart.Item;
^
symbol: class Item
location: package com.example.shop.cart
practice/src/com/example/shop/cart/Cart.java:4: error: cannot find symbol
private final List<Item> items = new ArrayList<>();
^
symbol: class List
location: class Cart
practice/src/com/example/shop/cart/Cart.java:4: error: cannot find symbol
private final List<Item> items = new ArrayList<>();
^
symbol: class Item
location: class Cart
practice/src/com/example/shop/cart/Cart.java:6: error: cannot find symbol
public void add(Item item) {
^
symbol: class Item
location: class Cart
practice/src/com/example/shop/app/Checkout.java:7: error: cannot find symbol
Cart cart = new Cart();
^
symbol: class Cart
location: class Checkout
practice/src/com/example/shop/app/Checkout.java:7: error: cannot find symbol
Cart cart = new Cart();
^
symbol: class Cart
location: class Checkout
practice/src/com/example/shop/app/Checkout.java:8: error: cannot find symbol
cart.add(new Item("notebook", 4_500, 2));
^
symbol: class Item
location: class Checkout
practice/src/com/example/shop/app/Checkout.java:9: error: cannot find symbol
cart.add(new Item("pen", 1_000, 3));
^
symbol: class Item
location: class Checkout
practice/src/com/example/shop/cart/Cart.java:4: error: cannot find symbol
private final List<Item> items = new ArrayList<>();
^
symbol: class ArrayList
location: class Cart
practice/src/com/example/shop/cart/Cart.java:16: error: cannot find symbol
for (Item item : items) {
^
symbol: class Item
location: class Cart
10 errors
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 practice_session.py
Fix the package declarations, the access levels and the imports, without moving any file, until these two commands
work from the folder that holds practice:
javac -d out $(find practice/src -name "*.java")prints nothing.java -cp out com.example.shop.app.Checkoutprints2 items, total 12000 paise.
Ten errors can come from very few mistakes, so read them in order and fix the first one first. A first hint: each error names a class it cannot find; ask which package that class is really in, and whether it may be used from there.
Then the questions on packages, imports and the class path. The part of this page your answers have missed most leads, and every choice comes with the reason it fits or fails:
Practice that adapts to you
Practise this lesson
15 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Fresher · What is the class path, and what is it when you set nothing?
The class path is the list of folders and JAR files where java and javac look for compiled classes that are not part
of the JDK, separated by : on Linux and macOS and by ; on Windows. You set it with -cp (or --class-path),
which overrides the CLASSPATH environment variable, and with neither it is just the current folder. A class in a
package is looked up by its path inside each entry, in order: com.example.app.Main is found as
com/example/app/Main.class under a folder of the class path, or inside one of its JAR files.
Two longer questions of this module start from this lesson: a program that compiles and then stops with
NoClassDefFoundError, and two JAR files on the class path that hold different versions of the same class.
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
Your program compiles, but at run time it stops with NoClassDefFoundError for a class from a library. What is different between compile time and run time, and how do you find and fix the cause?
-
Mid to senior
Two JAR files on the class path both contain com.acme.util.Strings, in different versions. What does the JVM do, how would you notice, and how do you fix it?
Key takeaways
- A package name maps to folders, one per part: keep each source file in the folder its package names, and run a
class with
java -cp out com.example.library.app.Main, by its full name. - An import changes only which simple names a file can use; an on-demand import covers one package, never its subpackages.
- Single-type imports shadow on-demand and module imports, and on-demand imports shadow module imports; two imports of the same kind that offer one name make it ambiguous, whatever the order of the lines.
- The class path is a list of folders and JAR files searched in order, and the first entry that has a class wins.
- A class that was there at compile time and is missing at run time gives
NoClassDefFoundError, at the first line that needs it; the fix is the class path, not the code.
Terms in this lesson
- fully qualified name
- A class's name with its package in front, such as com.example.library.model.Book. The JVM turns it into the path com/example/library/model/Book.class, and java runs a class in a package only by this name.
- JAR file
- A ZIP archive of class files kept in their package folders, with a manifest in META-INF/MANIFEST.MF. Put on the class path, it is searched for classes like a folder.
- module import
- An import module declaration, such as import module java.base; (JEP 511). It makes every public class and interface of every package the module exports usable by its simple name. Compact source files import java.base this way.
- on-demand import
- An import that ends in .*, such as import java.time.*;. It makes every public class and interface of one package usable by its simple name, but not those of its subpackages.
- single-type import
- An import of one class or interface by its full name, such as import java.util.List;. It shadows a class of the same simple name that an on-demand or module import would bring.
- static import
- An import static declaration, such as import static java.lang.Math.max;. It makes a static member of a class, or with .* all of them, usable without the class name in front.
References
- The Java Language Specification, Java SE 25: Chapter 7, Packages and Modules (Oracle)
- The Java Language Specification, Java SE 25: 7.2 Host Support for Modules and Packages (Oracle)
- The Java Language Specification, Java SE 25: 7.5 Import Declarations (Oracle)
- The Java Language Specification, Java SE 25: 6.1 Declarations (package naming) (Oracle)
- The Java Language Specification, Java SE 25: 6.4.1 Shadowing (Oracle)
- JEP 511: Module Import Declarations (OpenJDK)
- Module Import Declarations (Java SE 25 language guide) (Oracle)
- JEP 484: Class-File API (OpenJDK)
- JEP 458: Launch Multi-File Source-Code Programs (OpenJDK)
- The javac Command (Java SE 25): -d (Oracle)
- The java Command (Java SE 25): --class-path and --describe-module (Oracle)
- The jar Command (Java SE 25) (Oracle)
- Java SE 25 API: NoClassDefFoundError (Oracle)
- RFC 2606: Reserved Top Level DNS Names (IETF)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress