UKOnline

Librairie et package

En découvrant la documentation de la librairie standard Java à la section précédente, on a vu que les classes étaient organisées en packages. Il s'agit d'une des manières possibles de rassembler des classes. Dans cette section, on va voir les deux niveaux d'organisations que sont les librairies et les packages.

Librairie

Une librairie est un ensemble de classes Java qui offre des fonctionnalités formant un tout logique. Il y a par exemple des librairies pour manipuler des images, pour envoyer des e-mails, pour interagir avec le système d' exploitation, pour faire des animations 3D, etc. Un programme peut utiliser des librairies, ce qui aura pour conséquence qu'il dépendra de celles-ci. Elles devront donc être disponibles lors de la compilation, mais également lors de l'exécution du programme. L'annexe 2 donne une liste non-exhaustive de librairies Java.

Librairie standard Java

Il y a une librairie qui est toujours présente, c'est la librairie standard Java dont on vient de voir la documentation à la section précédente. Si vos programmes n'utilisent que les classes de ces librairies, il ne faudra rien faire de spécial pour pouvoir les compiler et les exécuter.

La librairie standard est communément appelée Java SE (Standard Edition). À ce jour, la dernière version est la 1.8 (Java SE 8). Il existe d'autres librairies standards adaptées chacune à une situation spécifique. Java EE (Enterprise Edition) est plus particulièrement destinée aux applications d'entreprise. Enfin, Java ME (Micro Edition) est spécialisée pour les applications embarquées.

Dépendance

Comme on vient de le dire, un programme Java dépend donc toujours de la librairie standard. Il peut également dépendre d'autres librairies. Celles-ci doivent être disponibles lors de la compilation du programme et lors de son exécution. Enfin, sachez également que des librairies peuvent avoir des liens de dépendance entre elles. La figure 19 montre un exemple de programme avec ses dépendances : la librairie standard, PICCOLO et jMusic. De plus, on voit que la librairie JUNG dépend de la librairie COLT. Notez également que toutes les librairies dépendent de la librairie standard.

Méthode sin de la classe Math
Librairie et dépendance.

Package

Les librairies sont une première manière d'organiser des classes. Un second niveau d'organisation est réalisé grâce aux packages (on lira parfois le mot paquetage dans la littérature française. Dans ce livre, on utilisera toujours le mot package). Ceux-ci rassemblent des classes autour d'une fonctionnalité précise et commune. Cette organisation en packages est importante pour gérer l'espace des noms de classes.

Il ne peut pas y avoir deux classes avec le même nom. Une telle contrainte est trop forte et il existe une solution pour avoir plusieurs classes avec le même nom : il faut les placer dans différents packages. Ensuite on distingue les différentes classes en utilisant leur nom qualifié complet, constitué du nom du package suivi d'un point et se terminant par le nom de la classe.

On est tombé sur un tel exemple dans la section précédente lorsqu'on cherchait la classe Date dans la librairie standard. Celle-ci contient en effet deux classes Date et elles se trouvent bien dans deux packages différents. Voici leurs noms qualifiés complets :

java.util.Date
java.sql.Date

La première classe Date se trouve donc dans le package java.util tandis que la seconde se trouve dans le package java.sql.

Il s'agit du second niveau d'organisation qui organise donc les classes d'une même librairie ou d'un même programme. Comme on le verra plus loin, il existe toujours un package implicite appelé le package par défaut, dans lequel toute classe se trouve donc, par défaut. Ce n'est pas une bonne pratique de l'utiliser.

Packages de la librairie standard

Les classes de la librairie standard sont organisées en packages. La figure 20 reprend quelques packages de la librairie standard avec une courte description. Le package java.lang est le package de base qui contient des classes qui seront presque toujours utilisées.

Package Description
java.applet Créer des programmes exécutables sur des pages web
java.awt Créer des interfaces graphiques natives (lourdes)
java.io Effectuer des opérations d'entrées/sorties
java.lang Contient les classes de base, par exemple System, String, etc.
java.math Effectuer des calculs en précision arbitraire
java.net Créer des programmes réseaux
java.text Manipulation de texte, dates, nombres indépendamment de la langue
java.util Contient des classes utilitaires comme Date par exemple
javax.swing Créer des interfaces graphiques (légères)
javax.xml Manipulation de documents XML
Quelques packages de la librairie standard Java.

Déclaration import

Lorsqu'on désire utiliser une classe particulière, il faut normalement toujours utiliser son nom qualifié complet pour que le programme compile. Donc, si on désire écrire un programme qui utilise une date, voici ce qu'il faut écrire :

Écrire un programme en utilisant toujours les noms qualifiés complets peut très vite le rendre complètement illisible. Pour rendre les choses plus claires, on peut utiliser une déclaration d'import. Une telle déclaration se fait avec le mot réservé import suivi d'un nom qualifié complet de classe. Une fois une classe importée, on peut utiliser son nom court dans le programme. Les déclarations d'import doivent se trouver au tout début du fichier, en dehors de toute classe, et on peut en avoir autant qu'on veut. La figure 21 montre le fichier .java complet qu'il faut écrire pour l'exemple précédent.

Le fichier TestAfter.java : Déclaration d'import.

Import multiple

Si vous désirez utiliser plusieurs classes se trouvant dans un même package, il peut également devenir pénible d'écrire une déclaration import par classe à importer. On peut importer toutes les classes d'un package en utilisant un astérisque ( * ) au lieu d'un nom de classe dans la déclaration d'import.

Pour importer toutes les classes du package java.util, il suffit d'écrire :

Quand on ne doit importer que quelques classes d'un package (moins de dix), il est de bon usage d'utiliser une déclaration import par classe. Lorsqu'on a plus de dix classes à importer, il devient plus lisible d'utiliser un import multiple. Vous pourriez vous demander pourquoi ne pas toujours utiliser l'import multiple, une réponse sera donnée à la fin de la section.

Les packages sont des structures indépendantes, et ne sont pas liés entre eux. Ainsi, le package java.awt.event par exemple, ne peut pas être considéré comme se trouvant dans le package java.awt. Concrètement, cela signifie que si vous faites un import java.awt.*, les classes faisant partie du package java.awt.event ne seront pas importées.

Pour importer toutes les classes du package java.util, il suffit d'écrire :

Quand on ne doit importer que quelques classes d'un package (moins de dix), il est de bon usage d'utiliser une déclaration import par classe. Lorsqu'on a plus de dix classes à importer, il devient plus lisible d'utiliser un import multiple. Vous pourriez vous demander pourquoi ne pas toujours utiliser l'import multiple, une réponse sera donnée à la fin de la section.

Les packages sont des structures indépendantes, et ne sont pas liés entre eux. Ainsi, le package java.awt.event par exemple, ne peut pas être considéré comme se trouvant dans le package java.awt. Concrètement, cela signifie que si vous faites un import java.awt.*, les classes faisant partie du package java.awt.event ne seront pas importées.

Package java.lang

Pour rappel, le package java.lang est un package qui contient des classes de bases qui sont très souvent utilisées. Ce package est importé implicitement dans tout programme Java. La déclaration suivante est donc toujours ajoutée par le compilateur :

L'import de la classe System qu'on a fait dans le programme de la figure 21 est donc inutile.

Import statique

Lorsqu'on souhaite appeler une méthode de classe, ou utiliser une constante de classe, on doit utiliser le nom de la classe suivi de l'opérateur d'appel et du nom de la méthode que l'on veut invoquer. Il faut bien entendu soit importer la classe, soit utiliser son nom qualifié complet.

Voici un exemple qui calcule la valeur absolue d'un nombre en utilisant la méthode abs de la classe Math qui se trouve dans le package java.lang :

La déclaration d'import statique, introduite dans Java 5, permet d'importer une méthode ou une constante de classe. On peut ainsi directement appeler une méthode de classe ou utiliser une constante de classe sans devoir préciser la classe d'où elle provient. On utilise les mots réservés import static suivi du nom qualifié complet de la classe suivi de la méthode ou de la constante à importer.

La figure 22 montre le fichier le fichier .java correspondant à l'exemple précédent revu avec une déclaration d'import statique. La méthode de classe abs de la classe Math a été importée, et peut donc être utilisée directement avec son nom.

Le fichier TestStaticImport.java : Déclaration d'import statique.

Si on désire importer plusieurs méthodes ou constantes de classe d'une même classe, on peut également utiliser l'astérisque. Par exemple, pour importer toutes les méthodes et constantes de classe de la classe java.lang.Math, on peut écrire :

Danger avec les imports

Lorsqu'on importe des classes ou des méthodes et constantes de classe, il faut faire attention aux problèmes d'ambigüité. En effet, il faut faire attention à ne pas importer deux classes ou méthodes qui portent le même nom. Si ceci se produit, le compilateur générera une erreur de compilation de type « The import XXX collides with another import statement ». Il est par exemple interdit d'avoir les deux déclarations d'import suivantes dans le même fichier :

Il est par contre tout à fait possible d'écrire les imports suivantes :

Mais, si vous utilisez le nom Date dans le programme, le compilateur va générer une erreur de type « The type Date is ambiguous ». En effet, le compilateur est incapable de deviner si vous voulez utiliser la classe java.util.Date ou java.sql.Date. C'est pour cette raison qu'on a tendance à éviter d'utiliser trop souvent les imports multiples, afin d'éviter ces conflits de nom.

Enfin, si vous tentez d'importer un package qui n'existe pas, ou qui n'est pas disponible car il manque une librairie que vous utilisez, le compilateur générera une erreur « package XXX does not exist ».