Les packages Java
Nous allons, durant ce chapitre, étudier le concept de package. Un package est en fait un regroupement de classes, travaillant conjointement sur le même domaine : en effet, il serait inutile de lier des classes qui non aucun rapport les unes avec les autres. Par contre, lier toutes les classes qui travaillent, par exemple, sur les flots de caractères, peut facilement sembler logique. Partant de cette idée les concepteur du langage ont développés une série de packages permettant d'utiliser l'ensemble des ressources de la machine (c'est l'API de Java). Chacun de ces packages ayant un domaine d'action bien déterminé, comme, par exemple, les connexions réseaux, les composants graphiques, ... Il vous est donc possible d'utiliser cet ensemble de packages (l'API) en spécifiant les packages dont vous avez besoin.
Mais vous pouvez, de plus, définir vos propres packages et les utilisez dans vos programmes. Nous allons donc, durant ce chapitre, voir comment on définit un package, comment on en utilise un, quel sont les intérêts, et quelques autres choses.
Création d'un package.
Nous allons donc, dans un premier temps, nous intéresser à la création des packages. Pour ce faire, deux étapes sont nécessaire. La première consiste à déterminer dans chaque fichier, à quel package il appartient. La seconde place les fichiers de bytecode générés à une position bien précise de l'arborescence de fichiers ("file system", en anglais) de votre support de stockage (disque dur ou autre). Reprenons en détail chacun de ces deux points.
Le mot clé package.
Nous devons donc, en premier lieu, indiquer pour chaque fichier de quel package il fait partie. Si vous ne spécifiez pas de package, le fichier appartient à un package qui vous est donné par défaut : par conséquent, tout fichier Java (et donc toute classe) appartient à un package, même si vous ne le spécifiez pas explicitement. Au niveau de la syntaxe, c'est très simple, il suffit d'ajouter le mot clé package suivit du nom du package auquel le fichier appartient et d'un point-virgule.
Placer les fichier d'un package.
Mais cela ne suffit pas à définir un package java. Il faut aussi correctement situer les fichiers de bytecode, ce en respectant une règle très précise. En effet, le nom du package doit correspondre à un emplacement sur le système de fichiers. Par exemple, le package de nom java.shape2D doit être placé dans un répertoire java/shape2D/ (ou java\shape2D\ sous certain système). Les points sont remplacés par un slash (ou anti-slash) au niveau de l'arborescence. Pour correctement placer les fichiers de bytecode, deux méthodes sont applicables : soit vous le faîtes à la main (bon courage), soit vous le faîte dans l'ordre de compilation du fichier. Dans ce dernier cas, il suffit de taper "javac -d repertoire file.java". L'option -d permet de spécifier le répertoire dans lequel sera stocké le code JVM (les .class). L'exemple qui suit intègre nos classes de figures 2D, définies dans le chapitre précédent, dans un package shape2D.
fichier "circle.java" |
package java.shape2D;
class Circle extends Shape {
...
} |
>mkdir java
>mkdir java/shape2D
>javac -d java/shape2D/ Circle.java
> |
Une petit remarque, si vous utilisez le package par défaut (vous n'avez donc pas préciser de package), le répertoire dans lequel doivent se trouver les fichier de bytecode est le répertoire courant, ce qui est en accord avec ce que nous avons déjà vu.
On est donc, désormais, capable de regrouper les classes selon des liens sémantiques. La question qui se pose maintenant est de savoir comment nous allons pouvoir utiliser ces packages dans nos programmes.
Importer les classes d'un package.
Comme nous allons le voir, il est possible d'utiliser les packages (ou seulement quelques classes) dans vos programme, notamment grâce au mot clé import. Mais pour que cela fonctionne, il faut correctement placer la variable d'environnement CLASSPATH de votre shell.
Correctement positionner la variable CLASSPATH.
Comme nous l'avons déjà mentionné dans ce cours, la variable d'environnement CLASSPATH permet de localiser l'ensemble des fichiers .class (ceux qui contiennent le bytecode), afin que la JVM puisse, lors de l'exécution d'un programme, charger le code nécessaire. En effet, la JVM ne charge pas directement tout le code de l'application, mais seulement la partie dont elle a besoin à un moment donné. Si par la suite, une classe est utilisée, sans que son code est déjà été chargé, alors la JVM se charge de le faire, en utilisant la variable CLASSPATH.
En fait, quand on définit un package, on regroupe un certain nombre de fichier de bytecode dans un répertoire particulier. Il faut donc pour que ce code soit utilisable, ajouter la racine de ce package à la variable CLASSPATH. Notez bien que ce doit être la racine et non le répertoire que l'on doit ajouter.
Maintenant que cela est compris, il ne nous reste plus qu'à voir comment on utilise un package.
Le mot clé import.
Nous allons, maintenant, voir qu'il Il existe plusieurs façons pour utiliser un package. En effet vous pouvez soit spécifier que vous utilisez un package complet, soit vous déterminez, un par un, les fichiers du package que vous voulez utiliser. Vous pourriez être amener à penser qu'il vaut mieux importer deux fichiers d'un package, plutôt que le package complet, surtout si celui-ci comporte de nombreux autres fichiers. Il en est rien. En effet, comme je l'ai dit, il y a quelque instant, les fichiers ne sont pas tous chargés dés le début de l'exécution du programme, mais dynamiquement, et seulement si besoin est. On n'augmente donc pas la place mémoire prise par le programme, lors de son déroulement. En fait, quand vous spécifiez que vous importez un package, vous donnez juste une indication quant à la localisation des fichiers le constituant. Il est donc préférable d'importer un package complet, plutôt que d'importer quelques fichiers d'un même package.
Pour importer une classe d'un package, on utilise le mot clé import suivit du nom du package (associé à un répertoire, rappelons le), d'un point, du nom de la classe et d'un point-virgule. Dès lors que votre programme contient une telle déclaration d'importation, vous pouvez y utiliser la classe. Si vous voulez importer directement le package complet, il vous suffit de remplacer le nom de la classe par un signe multiplié (*). Ce mécanisme est repris sur l'utilisation de joker dans les systèmes de fichiers, ce qui est d'ailleurs logique, quand on pense qu'à une classe est associé un fichier portant le même nom (nous verrons dans une section suivante que cela n'est pas toujours vrai).
fichier "exemple.java" |
import java.awt.Button; // On importe la classe Button
import java.shape2D.*; // On importe toutes les classes
class Exemple {
static void main(String argv[]){
Circle c1=new Circle();
...
}
} |
Accéder directement à une classe d'un package.
Mais il n'est pas obligé d'importer un package pour pouvoir en utiliser quelques fonctionnalités. En effet, vous pouvez accéder à une classe en spécifiant sa localisation complète, directement dans le code. L'exemple suivant sera plus explicite.
fichier
"exemple.java" |
class Exemple {
static void main(String argv[]){
java.shape2D.Circle c1=new java.shape2D.Circle();
...
}
} |
Compresser un package.
Comme nous le verrons plus tard, les programmes Java peuvent être amenés à circuler sur le réseau et comme tout le monde sait que le transfert de données y est pas franchement très rapide, il a fallut minimiser la taille des données qui y transitent. Dans cet objectif, les concepteur du langage y ont introduit la notion d'archive Java. Ces archives (d'extension .jar), au format ZIP contiennent les fichiers de bytecode (d'extension .class), et donc les packages. Les archives Java permettent aussi une diffusion plus efficace des programmes : en effet, on n'a plus qu'à transférer un seul fichier au lieu de tous ceux constituant le programme.
L'utilitaire jar
Afin de pouvoir facilement créer vos archives Java, l'utilitaire jar vous est proposé dans le JDK. Son utilisation est très simple et similaire à celle d'autre outils d'archivage que l'on peut notamment trouver sur les stations Unix. Voici quelques informations sur l'utilisation de cet utilitaire.
Usage: jar {ctx}[vf0] [jar-file] files ...
Options:
c crée une nouvelle archive
t liste le contenu d'une archive
x restitue les fichiers nommés (tous par défaut) d'une archive
v génère un affichage sur la sortie standard d'erreur
f spécifie le nom de l'archive
0 annule la compression de l'archive
Exemple: pour archiver deux fichiers (f1.class et f2.class) dans une nouvelle archive (a1.jar), procédez de la manière suivante : |
jar cvf a1.jar f1.class f2.class |
Encore quelques informations supplémentaires. Tout d'abord, si un nom de fichier correspond à un répertoire, alors se dernier sera archivé dans son intégralité (ceci peut sembler normal, mais sachez que certains utilitaires ne procèdent pas récursivement par défaut). Ensuite, l'option 0 permet de pouvoir accéder à l'archive directement à partir de la variable d'environnement CLASSPATH, mais regardons cela plus sérieusement.
La variable d'environnement CLASSPATH.
Une fois votre package archivé il est possible de l'utiliser, ce à condition que la variable d'environnement CLASSPATH contienne le chemin d'accès de l'archive (y compris le nom du fichier de l'archive). Cependant une restriction doit être observée : l'archive ne doit pas être compressée (en utilisant l'option O lors de la création de cette dernière).
Une petite subtilité.
Une petite subtilité apparaît lors de l'utilisation de package archivés, ce au travers d'un réseaux. En effet, la JVM charge une classe lors de sa première utilisation (et non pas au commencement du programme), ce qui est appréciable lorsque l'on utilise un réseau (souvent lent). Mais quand le code de la classe se trouve dans une archive, c'est l'archive complète qui est transférée et par conséquent toutes les autres classes. Par contre, une fois l'archive transférée sur la machine cliente, la JVM n'en extraira que le fichier requis. Mais en fait cela n'est pas très important, et le programme fera dans tous les cas ce qui lui est demandé.
Nous verrons plus loin dans ce cours, que les archives Java sont aussi utilisées avec les applets Java (en fait une application standard mais qui s'exécute forcément dans un navigateur internet). Nous en avons donc finit avec la notion de package Java. Celle-ci manquée pour étudier quelques autres concepts liés à la programmation orientée objet. Nous pouvons donc, maintenant, les appréhender.
|