W3docs

Créer des packages personnalisés en Java

Créez vos propres packages Java : structure de répertoires, déclaration package et compilation.

Lire les packages des autres est une chose. Créer les vôtres ne demande que trois petites étapes : choisir un nom, organiser le répertoire et placer la bonne déclaration package en haut de chaque fichier. Le compilateur et la JVM s'accordent sur une convention stricte, et une fois que vous l'avez appliquée deux fois, cela devient un réflexe. Si vous découvrez la notion de packages, commencez par l'aperçu Java packages ; ce chapitre se concentre sur la création des vôtres.

Les trois règles

Tout ce que vous écrivez à l'intérieur d'un package doit respecter exactement trois règles :

  1. La première instruction non commentée du fichier est la déclaration package. Aucune autre instruction ne peut la précéder.
  2. Le chemin du fichier reflète le nom du package. com.example.util.Strings doit se trouver à com/example/util/Strings.java sous une racine source.
  3. Le fichier porte le nom de sa classe publique de premier niveau. Strings.java pour public class Strings.

C'est tout. Tout le reste relève de la convention.

Choisir un nom de package

Le compilateur n'impose que les trois règles ci-dessus, mais quelques conventions de nommage permettent de garder vos packages sans collision et idiomatiques :

  • Tout en minuscules. com.w3docs.greet, jamais com.W3Docs.Greet. Les lettres majuscules dans les noms de packages fonctionnent mais brisent la convention que tout développeur Java attend, et elles posent des problèmes sur les systèmes de fichiers insensibles à la casse.
  • Inversez votre nom de domaine. Si vous possédez w3docs.com, vos packages commencent par com.w3docs. Cela garantit une unicité globale afin que votre Greeter n'entre jamais en conflit avec celui de quelqu'un d'autre sur le classpath.
  • Pas de mots-clés Java. Un segment de package ne peut pas être un mot réservé. Si votre domaine était int.example.com, vous ne pourriez pas écrire com.example.int — vous l'échappez, par exemple com.example.int_.
  • Pas de chiffre en tête d'un segment. com.3m.tape est illégal car 3m n'est pas un identifiant valide ; une correction courante est com._3m.tape.

Si vous ne déclarez aucun package, vos classes atterrissent dans le package par défaut — convenable pour un extrait de code jetable, mais les classes qui s'y trouvent ne peuvent pas être importées par du code packageté, donc évitez-le dans les vrais projets.

Un exemple minimal

Supposons que vous vouliez un petit package utilitaire appelé com.w3docs.greet. Voici la structure :

project/
└── src/
    └── com/
        └── w3docs/
            └── greet/
                ├── Greeter.java
                ├── Greeting.java
                └── Main.java

Greeting.java :

package com.w3docs.greet;

public record Greeting(String language, String text) {}

Greeter.java :

package com.w3docs.greet;

public class Greeter {
  public Greeting greet(String name) {
    return new Greeting("en", "Hello, " + name + "!");
  }
}

Main.java :

package com.w3docs.greet;

public class Main {
  public static void main(String[] args) {
    System.out.println(new Greeter().greet("Ada").text());
  }
}

Les trois fichiers commencent par la même ligne package com.w3docs.greet;. Parce qu'ils partagent un package, Greeter et Main peuvent utiliser Greeting sans import — vous n'importez que les types d'autres packages.

Compiler et exécuter depuis la ligne de commande

Depuis la racine project/, les commandes canoniques sont :

# Compile every .java file under src/ into a parallel tree under out/
javac -d out $(find src -name "*.java")

# Run a main class by its fully-qualified name, telling the JVM where out/ is.
java -cp out com.w3docs.greet.Main

-d out indique à javac où placer les fichiers .class compilés ; il préserve la structure de répertoires du package. -cp out (classpath) indique à java comment les trouver à l'exécution — le prochain chapitre sur le Java classpath entre dans les détails.

Si la déclaration de package ne correspond pas à l'emplacement du fichier par rapport à la racine source, javac l'accepte (le package est ce qui est déclaré, non ce qui est déduit du chemin) — mais java échouera à l'exécution avec NoClassDefFoundError. Gardez toujours les deux en synchronisation.

Les sous-packages ne sont pas imbriqués

Il est tentant de penser que com.example « contient » com.example.util, mais pour le compilateur Java ce sont deux packages sans rapport qui partagent simplement un préfixe de nom. Une classe dans com.example n'a pas d'accès particulier aux membres package-private de com.example.util. Il n'existe pas d'héritage de package.

Ce que les sous-packages vous apportent, c'est une arborescence de répertoires facile à naviguer et un endroit logique pour regrouper du code lié. La plupart des vrais projets utilisent des sous-packages par fonctionnalité (auth, billing, parser) ou par couche (controller, service, repository) — mais aucun de ces choix ne confère au sous-package un accès supplémentaire.

Unités de compilation et package-info.java

Un fichier .java est aussi appelé une unité de compilation, et il peut contenir :

  • Une déclaration package (ou aucune, pour le package par défaut).
  • N'importe quel nombre de déclarations import.
  • N'importe quel nombre de déclarations de types, dont au plus une peut être public, et celle-là doit correspondre au nom du fichier.

Il existe aussi un fichier spécial nommé package-info.java dont le seul rôle est de porter la Javadoc et les annotations au niveau du package :

/**
 * Greeting utilities for the W3Docs Java book.
 */
@NullMarked
package com.w3docs.greet;

Pas de types — juste le commentaire, des annotations facultatives et la ligne package. Vous verrez cela dans les bibliothèques bien documentées.

Un exemple complet

Ce programme déclare deux types qui résideraient dans le même package dans un vrai projet et les utilise ensemble. Le widget exécutable aplatit la structure de fichiers pour que vous puissiez voir la mécanique dans une seule liste source, mais dans un vrai projet chaque type public résiderait dans son propre fichier .java sous la structure de répertoires présentée ci-dessus.

java— editable, runs on the server

Et ensuite

Les packages personnalisés couvrent le code que vous écrivez vous-même. La plupart du temps, cependant, vous vous appuierez sur les packages du JDK — les classes de la bibliothèque standard pour les collections, les entrées/sorties, le temps, etc. Le prochain chapitre est une visite guidée de ceux que vous utiliserez le plus souvent. Continuez vers Java built-in packages.

Pratique

Pratique
Un fichier source Java déclare `package com.example.util;` mais est compilé puis exécuté depuis un `.class` situé à `out/com/example/Strings.class`. Que se passe-t-il ?
Un fichier source Java déclare `package com.example.util;` mais est compilé puis exécuté depuis un `.class` situé à `out/com/example/Strings.class`. Que se passe-t-il ?
Was this page helpful?