Java Packages
Table of Contents + โ
In the last lesson you learned about the Java protected access modifier. That word โpackageโ kept coming up, so now letโs really understand it. A package is one of the first things you need when a project grows past a handful of files. Letโs learn it.
๐ค The problem packages solve
One folder with forty Java files breaks in two ways:
- You cannot find anything. Users, payments, and email files all sit together.
- Names clash. Your
Date, JavaโsDate, and a libraryโsDatefight over one name. The compiler cannot tell which you mean.
A package fixes both. A package is a namespace that groups related classes together, and it gives each class a longer unique name. Think of folders on your computer. Photos go in one folder, invoices in another. Packages do that for your classes.
๐ฆ What a package actually is
A package is two things at once, and they must match:
- A folder on disk.
- A name in your code.
You create one with the package declaration at the very top of your file.
package com.shop.users;
public class User { String name = "Alex";
void greet() { System.out.println("Hi, I am " + name); }}What that line gives you:
- The class belongs to the package
com.shop.users. - Each dot is a folder level.
- So this file must live in
com/shop/users/. - The folders on disk must mirror the package name exactly.
Note
The package line must be the first real line of code in the file. Comments can come before it, but no other code can. We will see what happens if you break this rule later.
๐๏ธ Folders mirror the package name
Every dot is a folder. For com.shop.users, the files live here:
src/ com/ shop/ users/ User.java Admin.java payments/ Payment.java Card.javaThe rules:
- The name in the code and the path on disk must line up.
- Put
User.javain the wrong folder and the compiler complains. - The folder path is the address. Nothing else finds the file.
- Related classes group together.
UserandAdminshare one folder,PaymentandCardget their own.
๐ท๏ธ Naming convention: reverse domain
Use your domain name in reverse, all in lowercase. A company that owns shop.com starts with com.shop, then adds words for the project.
com.shop.userscom.shop.paymentsorg.redcross.donationsio.github.alex.notesThe reasons and the rules:
- Domain names are already unique. Nobody else owns
shop.com, so two companies never clash. - Reversing puts the broadest part first, broad to narrow, like folders.
- Use all lowercase.
com.shop.users, neverCom.Shop.Users. - Skip Java keywords.
com.shop.intfails becauseintis reserved. - Keep parts short and meaningful, so a reader can guess what is inside.
๐ Built-in packages you already use
Java ships with many built-in packages, and you have used them since your first program:
java.langholds basics likeString,System,Math,Integer. Imported for you automatically.java.utilholds tools likeScanner,ArrayList,HashMap,Random.java.ioholds classes for reading and writing files and streams.
Other packages you bring in yourself, which is the next lesson. Here is a tiny program that uses a class from java.util.
import java.util.Random;
public class Main { public static void main(String[] args) { Random r = new Random(); int roll = r.nextInt(6) + 1; // a number from 1 to 6 System.out.println("You rolled a number from 1 to 6"); }}Random lives in java.util, so we ask for it with import.
๐ Fully qualified class names
Every class has a short name and a long name:
- The short name is just
User. - The fully qualified name is the package path plus the class name:
com.shop.users.User. - The long name is always unique, because the package part is unique.
- Use the short name most of the time. The full name is handy when two classes share a short name.
Here we use java.util.Date by its full name, with no import at all.
public class Main { public static void main(String[] args) { java.util.Date now = new java.util.Date(); System.out.println("Created a Date object"); }}Output
Created a Date objectThe full name told the compiler exactly which Date we mean. No import needed. This is the escape hatch when two Date classes would clash.
โ๏ธ Compiling and running with packages
Packaged classes need a little care at the command line. Say you have this file at src/com/shop/users/User.java with a main method.
package com.shop.users;
public class User { public static void main(String[] args) { System.out.println("Hello from a packaged class"); }}Compile with -d to set the output folder.
javac -d out src/com/shop/users/User.javaThat builds out/com/shop/users/User.class, mirroring the package as folders again. To run it, give the fully qualified name, not the file path.
java -cp out com.shop.users.UserOutput
Hello from a packaged classThe key idea:
- A packaged class runs by its full dotted name.
- Use
com.shop.users.User, never the file nameUser.java. The package name is the address Java uses to find it.
Tip
Modern tools like IDEs and build tools such as Maven or Gradle handle all this for you. You will rarely type javac by hand on a real project. But knowing what happens underneath helps you read the errors when something breaks.
โ ๏ธ Common Mistakes
Putting the package statement below other code. The package line must be the first real statement. Only comments may sit above it. The fix: package first, then imports, then the class.
import java.util.Random; // โ import before packagepackage com.shop.users; // โ ERROR: class, interface, or enum expected
public class User { }package com.shop.users; // โ
package always comes firstimport java.util.Random; // โ
imports come after
public class User { }Folder path does not match the package name. Declare package com.shop.users; but save the file in a users folder with no com/shop above it, and the compiler cannot match the name to the location. The folders must spell out the full package.
src/ users/ User.java โ folder path does not match com.shop.userssrc/ com/ shop/ users/ User.java โ
folder path matches com.shop.usersLeaving classes in the default package. No package line means the class lands in the unnamed โdefault package.โ
- Fine for tiny throwaway code.
- A bad habit for real projects.
- Classes in a package cannot import default-package classes, so your code stops being reusable.
// โ no package line: this class is stuck in the default packagepublic class User { }package com.shop.users; // โ
give every real class a proper packagepublic class User { }โ Best Practices
- Give every class a real package. Keep the default package for throwaway tests.
- Name packages with your reversed domain, lowercase, like
com.shop.users. - Match the folder structure to the package name, level for level.
- Group related classes together. The package name should hint at what is inside.
- Lean on
java.lang,java.util,java.ioinstead of writing your own. - Use a fully qualified name only for a real name clash.
๐ What Youโve Learned
- A package is a namespace and a folder that groups related classes together.
- The
packagedeclaration must be the first line of code in the file. - Packages organize code, avoid name clashes, and shape access (as you saw with
protected). - The naming convention is reversed domain, lowercase, like
com.company.project. - The folder structure on disk must mirror the package name, dot for folder.
- Java ships with built-in packages such as
java.lang,java.util, andjava.io. - A fully qualified name is the package path plus the class name, like
com.shop.users.User, and you run a packaged class by that full name.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Where must the package declaration appear in a Java file?
Why: The package statement must be the first real statement in the file. Only comments may appear above it, and imports come after it.
- 2
What is the standard naming convention for packages?
Why: By convention packages use the reversed domain name in lowercase, which keeps names unique worldwide.
- 3
If a class declares package com.shop.users, where must the file live?
Why: The folder structure must mirror the package name. Each dot is a folder level, so the file lives in com/shop/users.
- 4
What is the fully qualified name of a User class in package com.shop.users?
Why: The fully qualified name is the full package path plus the class name: com.shop.users.User.
๐ Whatโs Next?
You now know how to group classes into packages and why it matters. But when a class in one package wants to use a class from another package, typing the full name every time gets long. Java gives you a cleaner way to pull in classes from other packages. That is the import statement, and it is what the next lesson is all about. Letโs learn it.