 |
 |
5) Cacher l'implémentation |
|
 |
|
Texte original |
 |
Traducteur :
Phillipe Boite |
|
 |
|
Ce chapitre contient
3 pages
1
2
3
|
|
|
 |
 |
 |
 |
 |
 |
|
 |
05.07.01 - version 1.2 [Armel] : - Ajout des tags de séparation des pages. - Remplacement des "foo" par « foo ». 25.04.2001 - version 1.1 [Armel] : - Mise en forme du code html (titres-hx[verdana], paragraphes-p[Georgia], code-blockquote). 08.06.2000 - version 1.0 [Philippe BOITE] : - Dernière mise à jour de la version française Traducteur : - Philippe BOITE Texte original : -Thinking in Java, 2nd edition, Revision 10 © 2000 by Bruce Eckel
|
 |
 |
 |
5: Hiding the Implementation
|
 |
5 : Cacher l'Implémentation
|
 |
 |
 |
A primary consideration in
object-oriented design is “separating the things that change from the
things that stay the same.”
|
 |
Une règle principale en conception orientée objet est de « séparer les
choses qui changent des choses qui ne changent pas ».
|
 |
 |
 |
This is particularly important for
libraries. The user (client programmer) of that
library must be able to rely on the part they use, and know that they
won’t need to rewrite code if a new version of the library comes out. On
the flip side, the library creator must have the freedom
to make modifications and improvements with the certainty that the client
programmer’s code won’t be affected by those
changes.
|
 |
Ceci est particulièrement important pour les bibliothèques
[libraries]. Les utilisateurs (programmeurs clients) de cette bibliothèque
doivent pouvoir s'appuyer sur la partie qu'ils utilisent, et savoir qu'ils n'auront pas à réécrire
du code si une nouvelle version de la bibliothèque sort. Inversement, le créateur de la
bibliothèque doit avoir la liberté de faire des modifications et améliorations avec la certitude
que le code du programmeur client ne sera pas affecté par ces modifications.
|
 |
 |
 |
This can be achieved through convention.
For example, the library programmer must agree to not remove existing methods
when modifying a class in the library, since that would break the client
programmer’s code. The reverse situation is thornier, however. In the case
of a data member, how can the library creator know which data members have been
accessed by client programmers? This is also true with methods that are only
part of the implementation of a class, and not meant to be used directly by the
client programmer. But what if the library creator wants to rip out an old
implementation and put in a new one? Changing any of those members might break a
client programmer’s code. Thus the library creator is in a strait jacket
and can’t change anything.
|
 |
On peut y parvenir à l'aide de conventions. Par exemple le programmeur de
bibliothèque doit admettre de ne pas enlever des méthodes existantes quand il modifie une classe
dans la bibliothèque, puisque cela casserait le code du programmeur. La situation inverse est plus
délicate. Dans le cas d'un membre de données, comment le créateur de bibliothèque peut-il savoir
quels membres de données ont été accédés par les programmeurs clients ? C'est également vrai avec
les méthodes qui ne sont qu'une partie de l'implémentation d'une classe et qui ne sont pas
destinées à être utilisées directement par le programmeur client. Mais que se passe-t-il si le
créateur de bibliothèque veut supprimer une ancienne implémentation et en mettre une nouvelle ?
Changer un de ces membres pourrait casser le code d'un programmeur client. De ce fait la marge de
manoeuvre du créateur de bibliothèque est plutôt étroite et il ne peut plus rien
changer.
|
 |
 |
 |
To solve this problem, Java provides
access specifiers to allow
the library creator to say what is available to the client programmer and what
is not. The levels of access control from “most
access” to “least access” are
public, protected,
“friendly” (which has no keyword),
and private. From the
previous paragraph you might think that, as a
library designer, you’ll
want to keep everything as “private” as possible, and expose only
the methods that you want the client programmer to use. This is exactly right,
even though it’s often counterintuitive for people who program in other
languages (especially C) and are used to accessing everything without
restriction. By the end of this chapter you should be convinced of the value of
access control in Java.
|
 |
Pour corriger ce problème, Java fournit des spécificateurs d'accès
pour permettre au créateur de bibliothèque de dire au programmeur client ce qui est disponible et
ce qui ne l'est pas. Les niveaux de contrôles d'accès, depuis le « plus accessible » jusqu'au « moins
accessible » sont public, protected (protégé), « friendly » (amical,
qui n'a pas de mot-clé), et private (privé). Le paragraphe précédent semble
montrer que, en tant que concepteur de bibliothèque, on devrait tout garder aussi « privé »
[private] que possible, et n'exposer que les méthodes qu'on veut que le programmeur client
utilise. C'est bien ce qu'il faut faire, même si c'est souvent non intuitif pour des gens qui
programment dans d'autres langages (particulièrement en C) et qui ont l'habitude d'accéder à tout
sans restrictions. Avant la fin de ce chapitre vous devriez être convaincus de l'importance du
contrôle d'accès en Java.
|
 |
 |
 |
The concept of a library of components
and the control over who can access the components of that library is not
complete, however. There’s still the question of how the components are
bundled together into a cohesive library unit. This is controlled with the
package keyword in Java, and the access specifiers are affected by
whether a class is in the same package or in a separate package. So to begin
this chapter, you’ll learn how library components are placed into
packages. Then you’ll be able to understand the complete meaning of the
access
specifiers.
|
 |
Le concept d'une bibliothèque de composants et le contrôle de qui peut
accéder aux composants de cette bibliothèque n'est cependant pas complet. Reste la question de
savoir comment les composants sont liés entre eux dans une unité de bibliothèque cohérente. Ceci
est contrôlé par le mot-clé package en Java, et les spécificateurs d'accès varient
selon que la classe est dans le même package ou dans un autre package. Donc, pour commencer ce
chapitre, nous allons apprendre comment les composants de bibliothèques sont placés dans des
packages. Nous serons alors capables de comprendre la signification complète des spécificateurs
d'accès.
|
 |
 |
 |
package: the library unit
|
 |
package : l'unité de bibliothèque
|
 |
 |
 |
A package is what
you get when you use the import keyword to bring
in an entire library, such as
|
 |
Un package est ce qu'on obtient lorsqu'on utilise le mot-clé
import pour apporter une bibliothèque complète, tel que
|
 |
 |
 |
import java.util.*;
|
 |
import java.util.*;
|
 |
 |
 |
This brings in the entire utility
library that’s part of the standard Java
distribution. Since, for example, the class ArrayList is in
java.util, you can now either specify the full name
java.util.ArrayList (which you can do without the import
statement), or you can simply say ArrayList (because of the
import).
|
 |
Cette instruction apporte la bibliothèque complète d'utilitaires qui font
partie de la distribution Java standard. Comme par exemple la classe ArrayList est
dans java.util, on peut maintenant soit spécifier le nom complet
java.util.ArrayList (ce qui peut se faire sans l'instruction
import), ou on peut simplement dire ArrayList (grâce à
l'instruction import).
|
 |
 |
 |
If you want to bring in a single class,
you can name that class in the import statement
|
 |
Si on veut importer une seule classe, on peut la nommer dans l'instruction
import :
|
 |
 |
 |
import java.util.ArrayList;
|
 |
import java.util.ArrayList;
|
 |
 |
 |
Now you can use ArrayList with no
qualification. However, none of the other classes in java.util are
available.
|
 |
Maintenant on peut utiliser ArrayList sans précision. Cependant, aucune des
autres classes de java.util n'est disponible.
|
 |
 |
 |
The reason for all this importing is to
provide a mechanism to manage “name spaces.”
The names of all your class members are insulated from each other. A method
f( ) inside a class A will not clash
with an f( ) that has the same signature (argument list) in class
B. But what about the class names? Suppose you create a stack
class that is installed on a machine that already has a stack class
that’s written by someone else? With Java on the Internet, this can happen
without the user knowing it, since classes can get downloaded automatically in
the process of running a Java program.
|
 |
La raison de tous ces imports est de fournir un mécanisme pour gérer les
« espaces de nommage » [name spaces]. Les noms de tous les membres de classe sont isolés les
uns des autres. Une méthode f() dans une classe A ne sera pas en
conflit avec une f() qui a la même signature (liste d'arguments) dans une classe
B. Mais qu'en est-il des noms des classes ? Que se passe-t-il si on crée une
classe stack qui est installée sur une machine qui a déjà une classe
stack écrite par quelqu'un d'autre ? Avec Java sur Internet, ceci peut se passer
sans que l'utilisateur le sache, puisque les classes peuvent être téléchargées automatiquement au
cours de l'exécution d'un programme Java.
|
 |
 |
 |
This potential clashing of names is why
it’s important to have complete control over the name spaces in Java, and
to be able to create a completely unique name regardless of the constraints of
the Internet.
|
 |
Ce conflit de noms potentiel est la raison pour laquelle il est important
d'avoir un contrôle complet sur les espaces de nommage en Java, et d'être capable de créer des noms
complètement uniques indépendamment des contraintes d'Internet.
|
 |
 |
 |
So far, most of the examples in this book
have existed in a single file and have been designed for local use, and
haven’t bothered with package names. (In this case the class name is
placed in the “default package.”) This is certainly an option, and
for simplicity’s sake this approach will be used whenever possible
throughout the rest of this book. However, if you’re planning to create
libraries or programs that are friendly to other Java programs on the same
machine, you must think about preventing class name clashes.
|
 |
Jusqu'ici, la plupart des exemples de ce livre étaient dans un seul fichier
et ont été conçus pour un usage en local, et ne se sont pas occupés de noms de packages (dans ce
cas le nom de la classe est placé dans le « package par défaut » ). C'est certainement une
possibilité, et dans un but de simplicité cette approche sera utilisée autant que possible dans le
reste de ce livre. Cependant, si on envisage de créer des bibliothèques ou des programmes amicaux
[friendly] vis-à-vis d'autres programmes sur la même machine, il faut penser à se prémunir
des conflits de noms de classes.
|
 |
 |
 |
When you create a source-code file for
Java, it’s commonly called a compilation
unit (sometimes a translation unit). Each
compilation unit must have a name ending in .java, and inside the
compilation unit there can be a public class that must have the same name
as the file (including capitalization, but excluding the .java filename
extension). There can be only one
public class in each
compilation unit, otherwise the compiler will complain. The rest of the classes
in that compilation unit, if there are any, are hidden from the world outside
that package because they’re not public, and they comprise
“support” classes for the main public class.
|
 |
Quand on crée un fichier source pour Java, il est couramment appelé une
unité de compilation [compilation unit](parfois une unité de traduction [translation
unit]). Chaque unité de compilation doit avoir un nom se terminant par .java,
et dans l'unité de compilation il peut y avoir une classe public qui doit avoir le
même nom que le fichier (y compris les majuscules et minuscules, mais sans l'extension .java ). Il
ne peut y avoir qu'une seule classe public dans chaque unité de compilation, sinon
le compilateur sortira une erreur. Le reste des classes de cette unité de compilation, s'il y en a,
sont cachées du monde extérieur parce qu'elles ne sont pas public, elles
sont des classes « support » pour la classe public principale.
|
 |
 |
 |
When you compile a .java file you
get an output file with exactly the same name but an extension of .class
for each class in the .java file. Thus you can end up with quite a
few .class files from a small number of .java files. If
you’ve programmed with a compiled language, you might be used to the
compiler spitting out an intermediate form (usually an “obj” file)
that is then packaged together with others of its kind using a linker (to create
an executable file) or a librarian (to create a library). That’s not how
Java works. A working program is a bunch of .class files, which can be
packaged and compressed into a JAR
file (using Java’s jar archiver). The Java interpreter is
responsible for finding, loading, and interpreting these
files[32].
|
 |
Quand on compile un fichier .java, on obtient un fichier
de sortie avec exactement le même nom mais avec une extension .class pour
chaque classe du fichier .java. De ce fait on peut obtenir un nombre important de fichiers
.class à partir d'un petit nombre de fichiers .java. Si vous avez
programmé avec un langage compilé, vous avez sans doute remarqué que le compilateur génère un
fichier de forme intermédiaire (généralement un fichier « obj » ) qui est ensuite assemblé avec
d'autres fichiers de ce type à l'aide d'un éditeur de liens [linker] (pour créer un
fichier exécutable) ou un « gestionnaire de bibliothèque » [librarian](pour créer une
bibliothèque). Ce n'est pas comme cela que Java travaille ; un programme exécutable est un ensemble
de fichiers .class, qui peuvent être empaquetés [packaged] et
compressés dans un fichier JAR (en utilisant l'archiveur Java jar). L'interpréteur
Java est responsable de la recherche, du chargement et de l'interprétation de ces fichiers [32].
|
 |
 |
 |
A library is also a bunch of these class
files. Each file has one class that is public (you’re not forced to
have a public class, but it’s typical), so there’s one
component for each file. If you want to say that all these components (that are
in their own separate .java and .class files) belong together,
that’s where the package keyword comes in.
|
 |
Une bibliothèque est aussi un ensemble de ces fichiers classes. Chaque
fichier possède une classe qui est public (on n'est pas obligé d'avoir une classe
public, mais c'est ce qu'on fait classiquement), de sorte qu'il y a un composant
pour chaque fichier. Si on veut dire que tous ces composants (qui sont dans leurs propres fichiers
.java et .class séparés) sont reliés entre eux, c'est là que le
mot-clé package intervient.
|
 |
 |
 |
When you say:
|
 |
Quand on dit :
|
 |
 |
 |
package mypackage;
|
 |
package mypackage;
|
 |
 |
 |
at the beginning of a file (if you use a
package statement, it must appear as the first noncomment in the
file), you’re stating that this compilation unit is part of a library
named mypackage. Or, put another way, you’re saying that the
public class name within this compilation unit is under the umbrella of
the name mypackage, and if anyone wants to use the name they must either
fully specify the name or use the import keyword in combination with
mypackage (using the choices given previously). Note that the convention
for Java package names is to use all lowercase letters, even for intermediate
words.
|
 |
au début d'un fichier (si on utilise l'instruction
package, elle doit apparaître à la première ligne du fichier,
commentaires mis à part), on déclare que cette unité de compilation fait partie d'une bibliothèque
appelée mypackage. Ou, dit autrement, cela signifie que le nom de la classe
public dans cette unité de compilation est sous la couverture du nom
mypackage, et si quelqu'un veut utiliser ce nom, il doit soit spécifier le nom
complet, soit utiliser le mot-clé import en combinaison avec mypackage
(utilisation des choix donnés précédemment). Remarquez que la convention pour les noms de packages
Java est de n'utiliser que des lettres minuscules, même pour les mots intermédiaires.
|
 |
 |
 |
For example, suppose the name of the file
is MyClass.java. This means there can be one and only one public
class in that file, and the name of that class must be MyClass (including
the capitalization):
|
 |
Par exemple, supposons que le nom du fichier est
MyClass.java. Ceci signifie qu'il peut y avoir une et une seule classe
public dans ce fichier, et que le nom de cette classe doit être
MyClass (y compris les majuscules et minuscules) :
|
 |
 |
 |
package mypackage;
public class MyClass {
// . . .
|
 |
package mypackage; public class MyClass { // . . .
|
 |
 |
 |
Now, if someone wants to use
MyClass or, for that matter, any of the other public classes in
mypackage, they must use the import keyword to make the name or
names in mypackage available. The alternative is to give the fully
qualified name:
|
 |
Maintenant, si quelqu'un veut utiliser MyClass ou, aussi
bien, une des autres classes public de mypackage, il doit
utiliser le mot-clé import pour avoir à sa disposition le ou les noms définis dans
mypackage. L'autre solution est de donner le nom complet :
|
 |
 |
 |
mypackage.MyClass m = new mypackage.MyClass();
|
 |
mypackage.MyClass m = new mypackage.MyClass();
|
 |
 |
 |
The import keyword can make this
much cleaner:
|
 |
Le mot-clé import peut rendre ceci beaucoup plus propre
:
|
 |
 |
 |
import mypackage.*;
// . . .
MyClass m = new MyClass();
|
 |
import mypackage.*; // . . . MyClass m = new MyClass();
|
 |
 |
 |
It’s worth keeping in mind that
what the package and import keywords allow you to do, as a library
designer, is to divide up the single global name space so you won’t have
clashing names, no matter how many people get on the Internet and start writing
classes in
Java.
|
 |
Il faut garder en tête que ce que permettent les mots-clés
package et import, en tant que concepteur de bibliothèque, c'est
de diviser l'espace de nommage global afin d'éviter le conflit de nommages, indépendamment de
combien il y a de personnes qui vont sur Internet écire des classes en Java.
|
 |
 |
 |
Creating unique package names
|
 |
Créer des noms de packages uniques
|
 |
 |
 |
You might observe that, since a package
never really gets “packaged” into a single file, a package could be
made up of many .class files, and things could get a bit cluttered. To
prevent this, a logical thing to do is to place all the .class files for
a particular package into a single directory; that is, use the hierarchical file
structure of the operating system to your advantage. This is one way that Java
references the problem of clutter; you’ll see the other way later when the
jar utility is introduced.
|
 |
On pourrait faire remarquer que, comme un package n'est jamais réellement
« empaqueté » [packaged] dans un seul fichier, un package pourrait être fait de nombreux
fichiers .class et les choses pourraient devenir un peu désordonnées. Pour éviter ceci, une chose
logique à faire est de placer tous les fichiers .class d'un package donné dans un
même répertoire ; c'est-à-dire utiliser à son avantage la structure hiérarchique des fichiers
définie par le système d'exploitation. C'est un des moyens par lequel Java traite le problème du
désordre ; on verra l'autre moyen plus tard lorsque l'utilitaire jar sera
présenté.
|
 |
 |
 |
Collecting the package files into a
single subdirectory solves two other problems: creating unique package names,
and finding those classes that might be buried in a directory structure
someplace. This is accomplished, as was introduced in Chapter 2, by encoding the
path of the location of the .class file into the name of the
package. The compiler enforces this, but by convention, the first part of
the package name is the Internet domain name of the creator of the class,
reversed. Since Internet domain names are guaranteed to be unique, if you
follow this convention it’s guaranteed that your package name will
be unique and thus you’ll never have a name clash. (That is, until you
lose the domain name to someone else who starts writing Java code with the same
path names as you did.) Of course, if you don’t have your own domain name
then you must fabricate an unlikely combination (such as your first and last
name) to create unique package names. If you’ve decided to start
publishing Java code it’s worth the relatively small effort to get a
domain name.
|
 |
Réunir les fichiers d'un package dans un même répertoire résoud deux autres
problèmes : créer des noms de packages uniques, et trouver ces classes qui pourraient être enfouies
quelque part dans la structure d'un répertoire. Ceci est réalisé, comme présenté dans le chapitre
2, en codant le chemin où se trouvent les fichiers .class dans le nom du
package. Le compilateur force cela ; aussi, par convention, la première partie du
nom de package est le nom de domaine Internet du créateur de la classe, renversé.
Comme les noms de domaines Internet sont garantis uniques, si on suit cette convention, il
est garanti que notre nom de package sera unique et donc qu'il n'y aura jamais de
conflit de noms (c'est-à-dire, jusqu'à ce qu'on perde son nom de domaine au profit de quelqu'un qui
commencerait à écrire du code Java avec les mêmes noms de répertoires). Bien entendu, si vous
n'avez pas votre propre nom de domaine vous devez fabriquer une combinaison improbable (telle que
votre prénom et votre nom) pour créer des noms de packages uniques. Si vous avez décidé de publier
du code Java, cela vaut la peine d'effectuer l'effort relativement faible d'obtenir un nom de
domaine.
|
 |
 |
 |
The second part of this trick is
resolving the package name into a directory on your machine, so when the
Java program runs and it needs to
load the .class file (which
it does dynamically, at the point in the program where it needs to create an
object of that particular class, or the first time you access a static
member of the class), it can locate the directory where the .class
file resides.
|
 |
La deuxième partie de cette astuce consiste à résoudre le nom de package à
l'intérieur d'un répertoire de sa machine, de manière à ce que lorsque le programme Java s'exécute
et qu'il a besoin de charger le fichier .class (ce qu'il fait dynamiquement, à
l'endroit du programme où il doit créer un objet de cette classe particulière, ou la première fois
qu'on accède à un membre static de la classe), il puisse localiser le répertoire où se trouve le
fichier .class.
|
 |
 |
 |
The Java interpreter proceeds as follows.
First, it finds the environment variable CLASSPATH (set
via the operating system, sometimes by the installation program that installs
Java or a Java-based tool on your machine). CLASSPATH contains one or more
directories that are used as roots for a search for .class files.
Starting at that root, the interpreter will take the package name and replace
each dot with a slash to generate a path name from the CLASSPATH root (so
package foo.bar.baz becomes foo\bar\baz or foo/bar/baz or
possibly something else, depending on your operating system). This is then
concatenated to the various entries in the CLASSPATH. That’s where it
looks for the .class file with the name corresponding to the class
you’re trying to create. (It also searches some standard directories
relative to where the Java interpreter resides).
|
 |
L'interpréteur Java procède de la manière suivante. D'abord il trouve la
variable d'environnement CLASSPATH (positionnée à l'aide du système
d'exploitation, parfois par le programme d'installation qui installe Java ou un outil Java sur
votre machine). CLASSPATH contient un ou plusieurs répertoires qui sont utilisés comme racines de
recherche pour les fichiers .class. En commençant à cette racine, l'interpréteur
va prendre le nom de package et remplacer chaque point par un « slash » pour construire un nom de
chemin depuis la racine CLASSPATH (de sorte que package foo.bar.baz devient
foo\bar\baz ou foo/bar/baz ou peut-être quelque chose d'autre,
selon votre système d'exploitation). Ceci est ensuite concaténé avec les diverses entrées du
CLASSPATH. C'est là qu'il recherche le fichier .class portant le nom correspondant à la classe
qu'on est en train d'essayer de créer (il recherche aussi certains répertoires standards
relativement à l'endroit où se trouve l'interpréteur Java).
|
 |
 |
 |
To understand this, consider my domain
name, which is bruceeckel.com. By reversing this, com.bruceeckel
establishes my unique global name for my classes. (The com, edu, org, etc.,
extension was formerly capitalized in Java packages, but this was changed in
Java 2 so the entire package name is lowercase.) I can further subdivide this by
deciding that I want to create a library named simple, so I’ll end
up with a package name:
|
 |
Pour comprendre ceci, prenons mon nom de domaine, qui est
bruceeckel.com. En l'inversant, com.bruceeckel établit le nom
global unique pour mes classes (les extensions com, edu, org, etc... étaient auparavant en
majuscules dans les packages Java, mais ceci a été changé en Java 2 de sorte que le nom de package
est entièrement en minuscules). Je peux ensuite subdiviser ceci en décidant de créer un répertoire
simplement nommé simple, de façon à obtenir un nom de package :
|
 |
 |
 |
package com.bruceeckel.simple;
|
 |
package com.bruceeckel.simple;
|
 |
 |
 |
Now this package name can be used as an
umbrella name space for the following two files:
|
 |
Maintenant ce nom de package peut être utilisé comme un espace de nommage
de couverture pour les deux fichiers suivants :
|
 |
 |
 |
//: com:bruceeckel:simple:Vector.java
// Creating a package.
package com.bruceeckel.simple;
public class Vector {
public Vector() {
System.out.println(
"com.bruceeckel.util.Vector");
}
} ///:~
|
 |
//: com:bruceeckel:simple:Vector.java // Création d'un package. package com.bruceeckel.simple; public class Vector { public Vector() { System.out.println( "com.bruceeckel.util.Vector"); } } ///:~
|
 |
 |
 |
When you create your own packages,
you’ll discover that the package statement must be the first
noncomment code in the file. The second file looks much the
same:
|
 |
Lorsque vous créerez vos propres packages, vous allez découvrir que
l'instruction package doit être le premier code non-commentaire du fichier. Le deuxième fichier
ressemble assez au premier :
|
 |
 |
 |
//: com:bruceeckel:simple:List.java
// Creating a package.
package com.bruceeckel.simple;
public class List {
public List() {
System.out.println(
"com.bruceeckel.util.List");
}
} ///:~
|
 |
//: com:bruceeckel:simple:List.java // Création d'un package. package com.bruceeckel.simple; public class List { public List() { System.out.println( "com.bruceeckel.util.List"); } } ///:~
|
 |
 |
 |
Both of these files are placed in the
subdirectory on my system:
|
 |
Chacun de ces fichiers est placé dans le sous-répertoire suivant dans mon
système :
|
 |
 |
 |
C:\DOC\JavaT\com\bruceeckel\simple
|
 |
C:\DOC\JavaT\com\bruceeckel\simple
|
 |
 |
 |
If you walk back through this, you can
see the package name com.bruceeckel.simple, but what about the first
portion of the path? That’s taken care of in the CLASSPATH environment
variable, which is, on my machine:
|
 |
Dans ce nom de chemin, on peut voir le nom de package
com.bruceeckel.simple, mais qu'en est-il de la première partie du chemin ? Elle
est prise en compte dans la variable d'environnement CLASSPATH, qui est, sur ma machine
:
|
 |
 |
 |
CLASSPATH=.;D:\JAVA\LIB;C:\DOC\JavaT
|
 |
CLASSPATH=.;D:\JAVA\LIB;C:\DOC\JavaT
|
 |
 |
 |
You can see that the CLASSPATH can
contain a number of alternative search paths.
|
 |
On voit que le CLASSPATH peut contenir plusieurs chemins de
recherche.
|
 |
 |
 |
There’s a variation when using JAR
files, however. You must put the name of the JAR file in the classpath, not just
the path where it’s located. So for a JAR named
grape.jar your classpath would include:
|
 |
Il y a toutefois une variante lorsqu'on utilise des fichiers JAR. Il faut
mettre également le nom du fichier JAR dans le classpath, et pas seulement le chemin où il se
trouve. Donc pour un JAR nommé grape.jar le classpath doit contenir :
|
 |
 |
 |
CLASSPATH=.;D:\JAVA\LIB;C:\flavors\grape.jar
|
 |
CLASSPATH=.;D:\JAVA\LIB;C:\flavors\grape.jar
|
 |
 |
 |
Once the classpath is set up properly,
the following file can be placed in any directory:
|
 |
Une fois le classpath défini correctement, le fichier suivant peut être
placé dans n'importe quel répertoire :
|
 |
 |
 |
//: c05:LibTest.java
// Uses the library.
import com.bruceeckel.simple.*;
public class LibTest {
public static void main(String[] args) {
Vector v = new Vector();
List l = new List();
}
} ///:~
|
 |
//: c05:LibTest.java // Utilise la bibliothèque. import com.bruceeckel.simple.*; public class LibTest { public static void main(String[] args) { Vector v = new Vector(); List l = new List(); } } ///:~
|
 |
 |
 |
When the compiler encounters the
import statement, it begins searching at the directories specified by
CLASSPATH, looking for subdirectory com\bruceeckel\simple, then seeking the
compiled files of the appropriate names (Vector.class for Vector
and List.class for List). Note that both the classes and the
desired methods in Vector and List must be
public.
|
 |
Lorsque le compilateur rencontre l'instruction import, il
commence à rechercher dans les répertoires spécifiés par CLASSPATH, recherchant le sous-répertoire
com\bruceeckel\simple, puis recherchant les fichiers compilés de noms appropriés (Vector.class pour
Vector et List.class pour List). Remarquez que chacune des classes et méthodes utilisées de
Vector et List doivent être public.
|
 |
 |
 |
Setting the CLASSPATH has been such a
trial for beginning Java users (it was for me, when I started) that Sun made the
JDK in Java 2 a bit smarter. You’ll find that, when you install it, even
if you don’t set a CLASSPATH you’ll be able to compile and run basic
Java programs. To compile and run the source-code package for this book
(available on the CD ROM packaged with this book, or at
www.BruceEckel.com), however, you will need to make some modifications to
your CLASSPATH (these are explained in the source-code
package).
|
 |
Positionner le CLASSPATH a posé tellement de problèmes aux utilisateurs
débutants de Java (ça l'a été pour moi quand j'ai démarré) que Sun a rendu le JDK un peu plus
intelligent dans Java 2. Vous verrez, quand vous l'installerez, que vous pourrez compiler et
exécuter des programmes Java de base même si vous ne positionnez pas de CLASSPATH. Pour compiler et
exécuter le package des sources de ce livre (disponible sur le CD ROM livré avec ce livre, ou sur
www.BruceEckel.com), vous devrez cependant faire
quelques modifications de votre CLASSPATH (celles-ci sont expliquées dans le package de
sources).
|
 |
 |
 |
Collisions
|
 |
Collisions
|
 |
 |
 |
What happens if two libraries are
imported via * and they include the same
names? For example, suppose a
program does this:
|
 |
Que se passe-t-il si deux bibliothèques sont importées à l'aide de * et
qu'elles contiennent les mêmes noms ? Par exemple, supposons qu'un programme fasse ceci
:
|
 |
 |
 |
import com.bruceeckel.simple.*;
import java.util.*;
|
 |
import com.bruceeckel.simple.*; import java.util.*;
|
 |
 |
 |
Since java.util.* also contains a
Vector class, this causes a potential collision. However, as long as you
don’t write the code that actually causes the collision, everything is
OK—this is good because otherwise you might end up doing a lot of typing
to prevent collisions that would never happen.
|
 |
Comme java.util.* contient également une classe
Vector, ceci crée une collision potentielle. Cependant, tant qu'on n'écrit pas le
code qui cause effectivement la collision, tout va bien ; c'est une chance, sinon on pourrait se
retrouver à écrire une quantité de code importante pour éviter des collisions qui n'arriveraient
jamais.
|
 |
 |
 |
The collision does occur if you
now try to make a Vector:
|
 |
La collision se produit si maintenant on essaye de créer un
Vector :
|
 |
 |
 |
Vector v = new Vector();
|
 |
Vector v = new Vector();
|
 |
 |
 |
Which Vector class does this refer
to? The compiler can’t know, and the reader can’t know either. So
the compiler complains and forces you to be explicit. If I want the standard
Java Vector, for example, I must say:
|
 |
A quelle classe Vector ceci se réfère-t-il ? Le
compilateur ne peut pas le savoir, et le lecteur non plus. Le compilateur se plaint et nous oblige
à être explicite. Si je veux le Vector Java standard, par exemple, je dois dire
:
|
 |
 |
 |
java.util.Vector v = new java.util.Vector();
|
 |
java.util.Vector v =new java.util.Vector();
|
 |
 |
 |
Since this (along with the CLASSPATH)
completely specifies the location of that Vector, there’s no need
for the import java.util.* statement unless I’m using something
else from
java.util.
|
 |
Comme ceci (avec le CLASSPATH) spécifie complètement l'emplacement de ce
Vector, il n'y a pas besoin d'instruction import java.util.*, à moins que
j'utilise autre chose dans java.util.
|
 |
 |
 |
A custom tool library
|
 |
Une bibliothèque d'outils personnalisée
|
 |
 |
 |
With this knowledge, you can now create
your own libraries of tools to reduce or eliminate duplicate code. Consider, for
example, creating an alias for System.out.println( ) to reduce
typing. This can be part of a package called tools:
|
 |
Avec ces connaissances, vous pouvez maintenant créer vos propres
bibliothèques d'outils pour réduire ou éliminer les duplications de code. On peut par exemple créer
un alias pour System.out.println( ) pour réduire la frappe. Ceci peut faire
partie d'un package appelé tools :
|
 |
 |
 |
//: com:bruceeckel:tools:P.java
// The P.rint & P.rintln shorthand.
package com.bruceeckel.tools;
public class P {
public static void rint(String s) {
System.out.print(s);
}
public static void rintln(String s) {
System.out.println(s);
}
} ///:~
|
 |
//: com:bruceeckel:tools:P.java // Les raccourcis P.rint & P.rintln package com.bruceeckel.tools; public class P { public static void rint(String s) { System.out.print(s); } public static void rintln(String s) { System.out.println(s); } } ///:~
|
 |
 |
 |
You can use this shorthand to print a
String either with a newline (P.rintln( )) or without a
newline (P.rint( )).
|
 |
On peut utiliser ce raccourci pour imprimer une String ,
soit avec une nouvelle ligne (P.rintln( )) , ou sans
(P.rint( )).
|
 |
 |
 |
You can guess that the location of this
file must be in a directory that starts at one of the CLASSPATH locations, then
continues com/bruceeckel/tools. After compiling, the P.class file
can be used anywhere on your system with an import
statement:
|
 |
Vous pouvez deviner que l'emplacement de ce fichier doit être dans un
répertoire qui commence à un des répertoire du CLASSPATH, puis continue dans
com/bruceeckel/tools. Après l'avoir compilé, le fichier P.class
peut être utilisé partout sur votre système avec une instruction import
:
|
 |
 |
 |
//: c05:ToolTest.java
// Uses the tools library.
import com.bruceeckel.tools.*;
public class ToolTest {
public static void main(String[] args) {
P.rintln("Available from now on!");
P.rintln("" + 100); // Force it to be a String
P.rintln("" + 100L);
P.rintln("" + 3.14159);
}
} ///:~
|
 |
//: c05:ToolTest.java // Utilise la bibliothèque tools import com.bruceeckel.tools.*; public class ToolTest { public static void main(String[] args) { P.rintln("Available from now on!"); P.rintln("" + 100); // Le force à être une String P.rintln("" + 100L); P.rintln("" + 3.14159); } } ///:~
|
 |
 |
 |
Notice that all objects can easily be
forced into String representations by putting them in a String
expression; in the above case, starting the expression with an empty
String does the trick. But this brings up an interesting observation. If
you call System.out.println(100), it works without casting it to a
String. With some extra overloading, you can get the P class to do
this as well (this is an exercise at the end of this chapter).
|
 |
Remarquez que chacun des objets peut facilement être forcé dans une
représentation String en les plaçant dans une expression String ;
dans le cas ci-dessus, le fait de commencer l'expression avec une String vide fait
l'affaire. Mais ceci amène une observation intéressante. Si on appelle
System.out.println(100), cela fonctionne sans le transformer [cast] en
String. Avec un peu de surcharge [overloading], on peut amener la classe P à faire
ceci également (c'est un exercice à la fin de ce chapitre).
|
 |
 |
 |
So from now on, whenever you come up with
a useful new utility, you can add it to the tools directory. (Or to your
own personal util or tools
directory.)
|
 |
A partir de maintenant, chaque fois que vous avez un nouvel utilitaire
intéressant, vous pouvez l'ajouter au répertoire tools (ou à votre propre
répertoire util ou tools).
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |