انتقل إلى المحتوى
أمين أبوزيد
منشورBEG-027-L01

الحزم والمجلدات

  • الدرس 1 من 5
  • 12 دقيقة قراءة
  • مبتدئ
في هذا الدرس 11 موضوعات

هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.

Lesson Overview

Until now, most of your classes have lived side by side in one folder. That works for a toy program. It stops working when a project has fifty classes and two of them are both called Account. Java's answer is the package: a named group of related classes that also gives each class a longer, unique full name.

Think of a filing cabinet. The cabinet is the project, each labeled drawer is a package, and each file in a drawer is a class. A drawer label tells you what is inside, and two drawers can each hold a document called "Summary" without any confusion.

Why this matters: every real Java backend project is organized into packages. The package line at the top of a file, and the folder that file sits in, are the first things you see in any codebase you join. Get this wrong and the compiler or the JVM will not find your classes.

This lesson builds on the encapsulation module, where you met the word package in a short preview of access levels. Here we teach it properly. The next lesson shows how code in one package uses classes from another.

Learning Objectives

By the end of this lesson you will be able to:

  • Explain what a package is and why Java has them.
  • Write a correct package line and place it where Java requires it.
  • Map a package name to a folder path, and a folder path to a package name.
  • Apply the naming conventions: lowercase names and a reversed domain prefix.
  • Compile and run a program whose classes sit in two packages, from a terminal.
  • Recognize the symptoms of a package line that does not match its folder.
  • Explain why a real project must not use the default (unnamed) package.

Written Explanation

What a package is

A package is a named group of related classes and interfaces. It does two jobs:

  1. Organization. Related classes are kept together, like papers in one drawer.
  2. A separate name space. The Java Language Specification explains that each package has its own namespace, so two packages can each contain a class with the same simple name. Its own example is java.util.Vector next to a different class also called Vector in another package.

A class's fully qualified name is its package name, a dot, and its simple name. For a class Account in package com.example.bank, the full name is com.example.bank.Account. Account alone is the simple name.

The package statement

The first line of a source file (ignoring comments and blank lines) declares which package the class belongs to:

java
package com.example.bank;

public class Account { }

Rules:

  • The package line comes before any import lines and before the class. The JLS says a package declaration, when present, comes first in the compilation unit.
  • There is at most one package line per file, and it ends with a semicolon.
  • Every class in a file belongs to the package named in that file.

Package name to folder path

Java source layout follows a simple rule: each dot in the package name is a folder separator. The Java Language Specification describes this for file-system based storage: a package jag.scrabble.board is held in the directories jag/scrabble/board/.

Package lineFolder (under your source root)Full file path
package com.example.bank;com/example/bank/com/example/bank/Account.java
package com.example.app;com/example/app/com/example/app/Main.java
package bank;bank/bank/Account.java

The folder where the package tree begins is called the source root. A package line always describes the path from the source root, never the full path on your disk. If your project is in C:\work\bank-demo\src, then src is the source root and the file Account.java for package com.example.bank belongs in src\com\example\bank\.

Naming conventions

The Oracle Java tutorial gives these conventions:

  • Package names are all lowercase, so they never look like class names.
  • Companies start with their reversed internet domain: a programmer at example.com names a package com.example.something. This keeps two organizations' packages from clashing.
  • Within one company or project, add a further part after the domain, such as com.example.bank.
  • Names beginning with java. or javax. belong to the Java platform itself. Do not use them.

If a domain is not a legal Java name (for example it contains a hyphen), the tutorial suggests replacing the hyphen with an underscore, so hyphenated-name.example.org becomes org.example.hyphenated_name.

For the lessons in this module we use the invented domain example.com, so our packages begin with com.example. In your own projects use a domain you control, or a clearly personal name.

The folder tree does not create packages by itself

A folder is not a package until a file inside it says so. Both must agree: the package line and the folder. If they disagree, tools stop finding your classes. That mismatch is the number-one beginner error with packages, and Example 3 shows it.

The default (unnamed) package

If a file has no package line, its classes belong to the unnamed package, usually called the default package. The JLS says the unnamed package is meant for small or temporary programs. It has a serious limit: types in the unnamed package cannot be imported by code that is in a named package. So the moment your project grows, classes in the default package cannot be used from properly organized code.

That is why "one giant default package" is the common mistake listed for this module. You may keep using it for a five-line experiment, but a project you intend to keep should have named packages from its first day.

Compiling and running with packages

You compile from the source root and tell the compiler where to put the .class files with -d. According to Oracle's javac documentation, -d sets the output directory, and the compiler places each class in a sub-folder that matches its package, creating folders as needed.

text
javac -d out src/com/example/bank/Account.java src/com/example/app/Main.java
java -cp out com.example.app.Main

Two things to notice:

  • You run a class by its fully qualified name (com.example.app.Main), not by its file name. -cp out tells the JVM where the compiled package folders start.
  • Oracle's documentation also describes -sourcepath, which tells javac where to look for other source files it needs. With javac -d out -sourcepath src src/com/example/app/Main.java you name only Main, and the compiler finds Account by itself.

(The commands above use forward slashes, which work in most Windows terminals as well. Exact terminal behavior can vary, so adjust to your shell. An IDE does all of this for you, but its menus and wording differ between products and versions, so follow your IDE's own help for "new package".)

Examples

Example 1: one class in a package (simple)

File src/com/example/bank/Account.java:

java
package com.example.bank;

public class Account {
    private final String owner;
    private double balance;

    public Account(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public String describe() {
        return owner + ": " + balance;
    }
}

The class is public so code in other packages may use it (the next lessons explain why that matters). The package line says com.example.bank, and the file sits in com/example/bank/. They agree.

Example 2: two packages, compiled and run (practical)

A second file, src/com/example/app/Main.java, uses the account. The import line is explained in the next lesson. For now read it as "make Account available here".

java
package com.example.app;

import com.example.bank.Account;

public class Main {
    public static void main(String[] args) {
        Account a = new Account("Sara", 100);
        a.deposit(50);
        System.out.println(a.describe());
        System.out.println(a.getClass().getName());
    }
}

The project tree:

text
src/
  com/example/bank/Account.java
  com/example/app/Main.java

Compile and run from the folder that contains src:

text
javac -d out -sourcepath src src/com/example/app/Main.java
java -cp out com.example.app.Main

Output (we compiled and ran this with JDK 21):

text
Sara: 150.0
com.example.bank.Account

The second line shows the fully qualified name: getName() returns the package plus the class name. The compiler also built this output tree, one folder per package segment:

text
out/com/example/app/Main.class
out/com/example/bank/Account.class

Example 3: the folder does not match the package line (realistic)

A beginner creates a folder src/bank/ and puts Account.java there, but leaves the line package com.example.bank; unchanged. Main still has import com.example.bank.Account;. Compiling with -sourcepath src:

text
error: package com.example.bank does not exist
import com.example.bank.Account;
                       ^
error: cannot find symbol
  symbol:   class Account
  location: class Main

The error message talks about the package not existing, which is confusing. The real cause is that the compiler looked for src/com/example/bank/Account.java, as the package name demands, and found nothing. Move the file to src/com/example/bank/ (or change both the package line and the imports to a shorter package, consistently). Your IDE usually shows this as a warning on the package line, and many IDEs offer a quick fix. Do not rely on one specific menu; check what your IDE suggests.

A related symptom happens at run time. Running java -cp out app.Main when the real class is com.example.app.Main fails with:

text
Error: Could not find or load main class app.Main
Caused by: java.lang.ClassNotFoundException: app.Main

Run the class with its full name.

Backend Insight

Backend projects have many classes: entities, services, data access, configuration. Packages are how teams find things and how they divide the work. In Java build tools such as Maven and Gradle, the convention is that sources sit under a src/main/java source root, and your package tree starts beneath it. Stack traces and log lines print fully qualified class names (com.example.bank.Account), so a clear package name tells you at a glance which part of the system a message came from.

Package names also matter beyond your own code. Frameworks, scanning tools and deployment files refer to your classes by full name. Renaming a package later means changing folders, package lines, imports and any configuration that mentions the old name, so choose a sensible name early. A reversed-domain prefix such as com.yourcompany.projectname is nearly universal.

Common Mistakes

Mistake 1: package line and folder disagree

  • Incorrect: package com.example.bank; in a file stored at src/bank/Account.java.
  • Correct: store it at src/com/example/bank/Account.java.

When you see "package ... does not exist" for a package you wrote yourself, check the folder first.

Mistake 2: leaving everything in the default package

Classes in the unnamed package cannot be imported from named packages. In our test, a class in a named package that wrote import Helper; for a default-package Helper got the error '.' expected, because an import needs a package name. Put your classes in packages from the beginning.

Mistake 3: the package line is not first

Placing import lines above the package line is a compile error. Order: package, then imports, then the class.

Mistake 4: capital letters and spaces in names

package Bank; compiles, but it breaks the convention and confuses readers, who expect capitalized names to be classes. Use lowercase. Also avoid spaces and hyphens, which are not legal in a package name.

Mistake 5: running a class by its file path

Use java -cp out com.example.app.Main, not a path to the file. The JVM wants the class's full name.

Exercises

Try each exercise yourself before opening the solutions.

Level A: Foundation

A1. A class Cart is declared with package com.acme.shop;. Under the source root src, what is the full path of its file?

أظهر الحل A1

A1. src/com/acme/shop/Cart.java.

A2. What is the fully qualified name of class Receipt in package org.nile.sales?

أظهر الحل A2

A2. org.nile.sales.Receipt.

A3. Which of these package names follows the convention, and what is wrong with the others? Com.Acme.Shop, com.acme.shop, shop-app.

أظهر الحل A3

A3. com.acme.shop follows the convention. Com.Acme.Shop uses capital letters, which are for class names. shop-app has a hyphen, which is not legal in a package name (and has no reversed-domain prefix).

Level B: Application

B1. You have src/org/nile/sales/Receipt.java and src/org/nile/app/Main.java, with Main using Receipt. Write the javac and java commands, using -d out, that compile and run it.

أظهر الحل B1

B1. From the folder that contains src:

text
javac -d out -sourcepath src src/org/nile/app/Main.java
java -cp out org.nile.app.Main

Listing both source files after javac -d out also works.

B2. A teammate's tree has the file src/sales/Receipt.java whose first line is package org.nile.sales;. Describe the compile error you expect when another class imports org.nile.sales.Receipt, and give two different fixes.

أظهر الحل B2

B2. The compiler looks for the package at org/nile/sales/ under the source root, does not find Receipt.java there, and reports something like package org.nile.sales does not exist plus cannot find symbol for Receipt. Fix 1: move the file to src/org/nile/sales/Receipt.java. Fix 2: change the package line to package sales; and update every import to match (less ideal, because the name lacks the reversed-domain prefix).

B3. Explain in two sentences why a growing project should not stay in the default package.

أظهر الحل B3

B3. Classes in the default package cannot be imported by classes in named packages, so the project cannot be organized into packages later without moving things. It also lacks the clear, unique full names that tools, logs and teammates rely on.

Level C: Challenge

C1. Your company owns the domain fast-pay.io. Propose the base package for a project called ledger, using the tutorial's rule for illegal characters. Then give the path of class Entry in the sub-package model.

أظهر الحل C1

C1. The tutorial suggests turning the hyphen into an underscore, giving the prefix io.fast_pay. The base package is io.fast_pay.ledger, and the class path is io/fast_pay/ledger/model/Entry.java with package io.fast_pay.ledger.model;.

C2. Two libraries both define a class called Invoice. Explain what feature of Java makes this possible, and what a class's full name would look like for each, if one comes from com.alpha.billing and the other from com.beta.billing.

أظهر الحل C2

C2. Each package has its own namespace, so the same simple name may appear in different packages. The full names are com.alpha.billing.Invoice and com.beta.billing.Invoice.

Mini Challenge

Create a small project on your own machine with this tree and make it run:

text
src/
  com/example/shop/Product.java
  com/example/app/Main.java

Product has a name and a price, both private, a constructor, and a public method label() that returns text such as Pen: 2.5. Main creates one product and prints its label and getClass().getName().

Check your work: both files have a package line that matches their folder; you compiled with -d out; and you launched Main using its full name. Then deliberately move Product.java to a wrong folder and read the error you get, as in Example 3. Put it back.

Summary & Next Lesson

Key takeaways

  • A package groups related classes and gives each a unique full name such as com.example.bank.Account.
  • The package line is the first statement in the file, and each dot in the name is one folder level from the source root.
  • Package names are lowercase and usually start with a reversed domain.
  • Compile with -d to get a matching .class folder tree, and run a class by its full name.
  • A package line that disagrees with the folder gives errors like package ... does not exist.
  • The default package cannot be imported from named packages, so real projects avoid it.

Next lesson

You can now place classes in packages, but Main in one package needed an import to see Account in another. The next lesson, "Imports and name clashes", explains how imports work and what to do when two classes share a simple name.

Self-check

  1. What does the package line package com.example.bank; tell you about the file's folder?
  2. Where in the file must the package line appear?
  3. Why do companies begin package names with a reversed domain?
  4. What is the fully qualified name of class Main in package com.example.app, and how do you run it?
  5. Name one problem with leaving a project in the default package.
أظهر الإجابات
  1. The file belongs in com/example/bank/ under the source root.
  2. First: before any import line and before the class declaration (comments and blank lines may precede it).
  3. It makes names unique, so packages from different organizations do not clash.
  4. com.example.app.Main; run it with java -cp out com.example.app.Main.
  5. Its classes cannot be imported from named packages, and it gives no unique full names, so it does not scale.

References

  • Oracle, The Java Language Specification, SE 21, Chapter 7: Packages and Modules. Supports the definition of packages and namespaces, the package declaration coming first, the unnamed package for small programs and its import restriction, and the mapping of package names to directories.
  • Oracle, The Java Tutorials: Naming a Package. Supports lowercase names, the reversed-domain convention, the java. and javax. reservation and the underscore rule for illegal characters.
  • Oracle, javac command reference (JDK 21). Supports what -d and -sourcepath do.
  • The compiler and run outputs shown were produced by running the code with JDK 21. The Maven/Gradle src/main/java convention in Backend Insight is general community practice that we did not verify against a source in this lesson.

التطبيق

طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.

المختبر والتمارين الاختبار

تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.

اكتب للبحث في المستويات والمراحل والوحدات والدروس.