☕ Java

Module, Pakete und Import in Java: Eine ausführliche Anleitung

What is it and why? (a real-life analogy)

Imagine you are building a huge spaceship from a LEGO set. You have a million pieces. If they were all lying in one big pile, you would spend hours looking for the right gear or a red 2×4 brick. Moreover, when you finish building the hull, you won't want those parts to get in the way when you start assembling the engine.

The same thing happens in programming. When a program becomes large (1000, 10,000, or 100,000 lines of code), storing everything in one file is a disaster. You'll get confused about where everything is, and your fellow programmers won't be able to work on different parts simultaneously.

Modules and packages in Java are your boxes and shelves for LEGO. A package is like a separate box labeled "Engine" or "Wings". A module is a whole shelving unit with such boxes. And an import is when you say: "I need a part from the 'Engine' box, let me get it."

Important: Packages help not only to organize but also to avoid naming conflicts. If you have two classes named "Button" — one for an elevator door, another for a program interface — they can live in different packages and not interfere with each other.

Why does a beginner need this? Even if you are writing a small program, the habit of organizing code into packages will make you a professional from day one. You will learn to think structurally, rather than dumping everything into one pile.

Theory: how it works internally

Let's look under the hood of Java and see how packages and imports work at the level of the Java Virtual Machine (JVM).

What is a package physically?

A package is simply a folder on your hard drive. If you create a package com.myproject.game, Java expects to see the folder com/myproject/game/. Inside this folder are files with the .java extension. The first line in each such file must be:

package com.myproject.game;

This is like a home address. Without this line, Java won't know which folder to put your class in.

How does Java find classes?

When you write import java.util.Scanner;, Java does the following:

  1. Looks at the package name: java.util.
  2. Goes to the java/util/ folder inside the standard library.
  3. Finds the file Scanner.class (already compiled) there.
  4. Loads it into memory so you can use it.

This is called the ClassLoader mechanism. It works like a librarian: you give it the name of a book (the fully qualified class name), and it brings it from the appropriate department.

Package hierarchy

Packages form a tree. For example:

  • java.lang — base classes (String, Math). Imported automatically.
  • java.util — utilities (Scanner, ArrayList).
  • java.io — file I/O.
  • java.net — networking.

You can create your own packages with any nesting depth. Usually, the structure used is: domain.company.project.module. For example: ru.school.lesson5.utils.

Modules (Java 9+)

With Java 9, the module system (Project Jigsaw) appeared. A module is a group of packages that explicitly declares what it provides to other modules (exports) and what it takes from them (requires). It's like a contract: "I, the 'Engine' module, give everyone the 'Turbine' class, but I don't let anyone inside me."

A module is described in the file module-info.java:

module com.myproject.engine {
    exports com.myproject.engine.core;  // Allow others to use this package
    requires java.sql;                  // We need this module
}

For beginners, modules might seem complicated, but in reality, they simply make explicit what was previously implicit: who allows what to whom.

Syntax in Java: all forms and variants

Let's break down all the ways to declare packages and imports. This is your cheat sheet for all occasions.

1. Package declaration

Always the first line in the file (before imports and class declaration):

package com.example.myapp;

If the line is missing, the class goes into the default package. This is bad practice for large projects, but for small examples, it's okay.

2. Importing a single class

The most common form:

import java.util.Scanner;

Now in the code, you can simply write Scanner instead of java.util.Scanner.

3. Importing all classes from a package (wildcard)

import java.util.*;

The asterisk * means "all classes from the java.util package". But there is a nuance: it does not import classes from nested packages! import java.util.* will not give you java.util.regex.Pattern.

Tip: Many textbooks criticize wildcard imports, saying they "pollute the namespace". For a beginner, this is fine. But when you become a pro, try to import only what you use. This makes the code clearer.

4. Importing static members (static import)

Allows you to use static methods and constants without specifying the class name:

import static java.lang.Math.PI;
import static java.lang.Math.sqrt;

// Now you can write:
double r = sqrt(25);  // instead of Math.sqrt(25)
double area = PI * r * r;  // instead of Math.PI

You can import all static members at once:

import static java.lang.Math.*;

5. Fully qualified name