Java packages give classes qualified names and group related types. Imports let a source file use selected simple names without repeatedly spelling their full packages. Understanding both helps you diagnose name conflicts and organize projects before they grow into dozens of files.
Review the related foundation lesson when you need a prerequisite. The complete programs below use Java 17-compatible syntax.
Qualified type names
A package gives a type a qualified name and helps organize related code. Put the package declaration before imports and type declarations.
A package declaration applies to the compilation unit and appears before imports and type declarations. package example.catalog gives a class a qualified name such as example.catalog.Book. Source trees conventionally mirror that name with matching directories. Use lowercase package names and a unique project or organization prefix for reusable libraries; descriptive package structure makes unrelated Book classes distinguishable.
What an import does
An import permits a shorter source-code name. It does not copy a library into the application or download a dependency.
An import changes name resolution in the source file. It does not copy source code, load a dependency or grant access to a private type. java.lang types such as String are available without an explicit import. A single-type import names one type, while a wildcard import makes accessible types in that package available for simple-name resolution. It does not include subpackages.
Implicit imports and subpackages
Types in java.lang are implicitly available. Other packages often need imports, and a wildcard import does not include subpackages.
Two packages may declare types with the same simple name. When both are needed, use a fully qualified name for one or both rather than expecting ambiguous wildcard imports to choose for you. Static imports similarly allow selected static members to be named without a type prefix. Use them sparingly when qualification carries important meaning, especially for common names such as count or max.
Package access and directories
Package-private members are accessible within their package. Directory structure should reflect package names in conventional builds so source files are easy to find.
Compilation and execution must still locate classes. With javac -d out, Java creates package directories under out for the compiled classes. Run a packaged entry point by its qualified name with the output directory on the classpath. The classpath root is the directory above the package folders, not the folder containing only the final class file.
Running the examples
Save each example under its public class name with a .java extension. The first uses a named package: compile with javac --release 17 -d out QualifiedToolList.java, then launch java -cp out demo.tools.QualifiedToolList. The other two have no package declaration and use the ordinary javac filename.java and java ClassName pattern. Imports belong before the class declaration.
How QualifiedToolList produces its output
The package declaration gives this class the qualified name demo.tools.QualifiedToolList. The import allows List to stand for java.util.List; it does not download that library. List.of creates Saw and Clamp at indexes zero and one, so get(1) returns Clamp. Save as QualifiedToolList.java, compile with javac --release 17 -d out QualifiedToolList.java, and launch with java -cp out demo.tools.QualifiedToolList. The output directory is the classpath root, above the demo/tools package directories.
How QualifiedList produces its output
The single-type import lets the compiler resolve both List names in the method. List.of creates Ada and Lin, and size reports two. Replacing the import with fully qualified java.util.List names would leave the output unchanged. This class has no package declaration, so compile QualifiedList.java and launch java QualifiedList. The import belongs before the class declaration and affects only this source file.
How StaticImportExample produces its output
The first import names one static method family from Math, so max can be called directly. The second imports a type, making LocalDate available by its simple name. max returns thirteen, and the date’s getMonthValue returns three. These two import forms shorten different kinds of names. They neither change the calculations nor grant access that the selected type or member would otherwise forbid.
A packaged program needs a qualified launch name
For a file declaring package demo.tools and public class ToolList, compile from the project root with javac -d out followed by the source path. The output is placed beneath out/demo/tools. Launch with java -cp out demo.tools.ToolList, not merely ToolList and not a filesystem path containing slashes. The runtime translates the qualified name into the package-directory lookup beneath the classpath root. This is why moving the classpath root into demo/tools usually fails. A source import cannot repair the launch command: imports were used during source compilation, while this error concerns locating the compiled entry class.
Java Summary
- A package gives a type a qualified name and helps organize related code. Put the package declaration before imports and type declarations.
- An import permits a shorter source-code name. It does not copy a library into the application or download a dependency.
- Types in java.lang are implicitly available. Other packages often need imports, and a wildcard import does not include subpackages.
- Package-private members are accessible within their package. Directory structure should reflect package names in conventional builds so source files are easy to find.
- Continue with Java exercises, Java quizzes and the Java study roadmap.
Java Examples
Each example shows the code, the output it produces and what each part does.
A package gives the class its qualified name
package demo.tools;
import java.util.List;
public class QualifiedToolList {
public static void main(String[] args) {
List<String> tools = List.of("Saw", "Clamp");
System.out.println(tools.get(1));
}
}ClampLine-by-line explanation
- Line 1Declares demo.tools as the package, making the binary name demo.tools.QualifiedToolList.
- Line 3Imports List so both uses in the method can use its simple name.
- Lines 7 to 8Creates two list positions and prints the second value, Clamp.
A type import shortens library names
import java.util.List;
public class QualifiedList {
public static void main(String[] args) {
List<String> names = List.of("Ada", "Lin");
System.out.println(names.size());
}
}2Line-by-line explanation
- Line 1Imports the java.util.List type for simple-name resolution.
- Lines 5 to 6Creates the two-element list and prints its size.
Static imports shorten selected member names
import static java.lang.Math.max;
import java.time.LocalDate;
public class StaticImportExample {
public static void main(String[] args) {
System.out.println(max(8, 13));
System.out.println(LocalDate.of(2025, 3, 2).getMonthValue());
}
}13
3Line-by-line explanation
- Line 1Imports the static max member, allowing a call without the Math prefix.
- Line 2Imports LocalDate as a type; this is different from importing one static member.
- Lines 6 to 7Prints the larger number, thirteen, and the constructed date’s month number, three.
Java FAQ
Does importing java.util.* import subpackages?
No. It covers accessible types directly in java.util for simple-name resolution, not types in java.util.concurrent or other subpackages. Import those types explicitly or use their qualified names. Packages have hierarchical names, but wildcard imports do not recurse.
Why does importing a library not fix a missing dependency?
The import tells the compiler which type name you mean. The actual class must still be available on the compilation classpath or module path, and required classes must also be available at runtime. A dependency manager supplies artifacts; an import supplies a source-level name.
How should Java packages be named?
Use lowercase names based on a domain you control, written in reverse: com.example.shop.orders. This makes names unique across libraries from different organisations. Small learning projects can use a simple name such as demo.tools, but avoid starting your own packages with java.
What if two imported classes have the same name?
Import one and refer to the other by its fully qualified name. The classic case is java.util.Date and java.sql.Date: write import java.util.Date; and use java.sql.Date in full where needed. Importing both with single-type imports doesn't compile.
Are wildcard imports bad for performance?
No. Imports only affect how the compiler resolves names, so import java.util.*; produces the same bytecode as individual imports. Many teams still prefer single-type imports because they show exactly which classes a file uses and avoid name clashes when a library adds classes later.
Java Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
What does an import do?
Which name identifies a packaged class completely?
Java Quiz
2 questions to check what you learned.
Does java.util.* include java.util.concurrent types?
- No
- Yes recursively
- Only when main is static
Where should a classpath root point for packaged output?
- Above the package directory tree
- Inside the last package directory
- At the Java source method