 |
 |
4) Initialisation & nettoyage |
|
 |
|
Texte original |
 |
Traducteur : F. DEFAIX et Y. CHICHA |
|
 |
///
|
Ce chapitre contient 6 pages
1
2
3
4
5
6
|
|
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
There are a number of additional speedups
possible in a JVM. An especially important one involves the operation of the
loader and Just-In-Time (JIT) compiler. When a class must be loaded (typically,
the first time you want to create an object of that class), the .class
file is located and the byte codes for that class are brought into memory. At
this point, one approach is to simply JIT all the code, but this has two
drawbacks: it takes a little more time, which, compounded throughout the life of
the program, can add up; and it increases the size of the executable (byte codes
are significantly more compact than expanded JIT code) and this might cause
paging, which definitely slows down a program. An alternative approach is
lazy evaluation, which means that the code is not JIT compiled until
necessary. Thus, code that never gets executed might never get JIT
compiled.
|
 |
Il existe un certain nombre d'autres optimisations possibles dans une JVM.
Une d'entre elles, très importante, implique le module de chargement des classes et le compilateur
Just-In-Time (JIT). Quand une classe doit être chargée (généralement la première fois que l'on veut
créer un objet de cette classe), le fichier .class est trouvé et le byte-code pour
cette classe est chargé en mémoire. A ce moment-là, une possibilité est d'utiliser le JIT sur tout
le code, mais cela a deux inconvénients. Tout d'abord c'est un peu plus coûteux en temps et, quand
on considère toutes les classes chargées sur la durée de vie du programme, cela peut devenir
conséquent. De plus, la taille de l'exécutable est augmentée (les byte codes sont bien plus
compacts que le code résultant du JIT) et peut donc causer l'utilisation de pages dans la mémoire
virtuelle, ce qui ralentit clairement le programme. Une autre approche est l'évaluation
paresseuse qui n'utilise le JIT que lorsque cela est nécessaire. Par conséquent, si une partie
du code n'est jamais exécutée, il est possible qu'elle ne soit jamais compilée par le
JIT.
|
 |
 |
 |
Member initialization
|
 |
Initialisation de membre
|
 |
 |
 |
Java goes out of its way to guarantee
that variables are properly initialized before they are used. In the case of
variables that are defined locally to a method, this guarantee comes in the form
of a compile-time error. So if you say:
|
 |
Java prend en charge l'initialisation des variables avant leur utilisation.
Dans le cas des variables locales à une méthode, cett garantie prend la forme d'une erreur à la
compilation. Donc le code suivant :
|
 |
 |
 |
void f() { int i; i++; }
|
 |
void f() { int i; i++; }
|
 |
 |
 |
you’ll get an error message that
says that i might not have been initialized. Of course, the compiler
could have given i a default value, but it’s more likely that this
is a programmer error and a default value would have covered that up. Forcing
the programmer to provide an initialization value is more likely to catch a
bug.
|
 |
générera un message d'erreur disant que la variable i peut
ne pas avoir été initialisée. Bien entendu, le compilateur aurait pu donner à i
une valeur par défaut, mais il est plus probable qu'il s'agit d'une erreur de programmation et une
valeur par défaut aurait masqué ce problème. En forçant le programmeur à donner une valeur par
défaut, il y a plus de chances de repérer un bogue.
|
 |
 |
 |
If a
primitive
is a data member of a class, however, things are a bit different. Since any
method can initialize or use that data, it might not be practical to force the
user to initialize it to its appropriate value before the data is used. However,
it’s unsafe to leave it with a garbage value, so each primitive data
member of a class is guaranteed to get an initial value. Those values can be
seen here:
|
 |
Cependant, si une valeur primitive est un membre de données d'une classe,
les choses sont un peu différentes. Comme n'importe quelle méthode peut initialiser ou utiliser
cette donnée, il ne serait pas très pratique ou faisable de forcer l'utilisateur à l'initialiser
correctement avant son utilisation. Cependant, il n'est pas correct de la laisser avec n'importe
quoi comme valeur, Java garantit donc de donner une valeur initiale à chaque membre de données avec
un type primitif. On peut voir ces valeurs ici :
|
 |
 |
 |
//: c04:InitialValues.java // Shows default initial values.
class Measurement { boolean t; char c; byte b; short s; int i; long l; float f; double d; void print() { System.out.println( "Data type Initial value\n" + "boolean " + t + "\n" + "char [" + c + "] "+ (int)c +"\n"+ "byte " + b + "\n" + "short " + s + "\n" + "int " + i + "\n" + "long " + l + "\n" + "float " + f + "\n" + "double " + d); } }
public class InitialValues { public static void main(String[] args) { Measurement d = new Measurement(); d.print(); /* In this case you could also say: new Measurement().print(); */ } } ///:~
|
 |
//: c04:InitialValues.java // Imprime les valeurs initiales par défaut.
class Measurement { boolean t; char c; byte b; short s; int i; long l; float f; double d; void print() { System.out.println( "Data type Initial value\n" + "boolean " + t + "\n" + "char [" + c + "] "+ (int)c +"\n"+ "byte " + b + "\n" + "short " + s + "\n" + "int " + i + "\n" + "long " + l + "\n" + "float " + f + "\n" + "double " + d); } }
public class InitialValues { public static void main(String[] args) { Measurement d = new Measurement(); d.print(); /* Dans ce cas, il est également possible d'écrire : new Measurement().print(); */ } } ///:~
|
 |
 |
 |
The output of this program
is:
|
 |
Voici la sortie de ce programme :
|
 |
 |
 |
Data type Initial value boolean false char [ ] 0 byte 0 short 0 int 0 long 0 float 0.0 double 0.0
|
 |
Data type Initial value boolean false char [ ] 0 byte 0 short 0 int 0 long 0 float 0.0 double 0.0
|
 |
 |
 |
The char value is a zero, which
prints as a space.
|
 |
La valeur pour char est zéro, ce qui se traduit par un
espace dans la sortie-écran.
|
 |
 |
 |
You’ll see later that when you
define an object reference inside a class without initializing it to a new
object, that reference is given a special value of null (which is a Java
keyword).
|
 |
Nous verrons plus tard que quand on définit une référence sur un objet dans
une classe sans l'initialiser avec un nouvel objet, la valeur spéciale null
(mot-clé Java) est donnée à cette référence.
|
 |
 |
 |
You can see that even though the values
are not specified, they automatically get initialized. So at least there’s
no threat of working with uninitialized
variables.
|
 |
On peut voir que même si des valeurs ne sont pas spécifiées, les données
sont initialisées automatiquement. Il n'y a donc pas de risque de travailler par inattention avec
des variables non-initialisées.
|
 |
 |
 |
Specifying initialization
|
 |
Spécifier une initialisation
|
 |
 |
 |
What happens if you want to give a
variable an initial value? One direct way to do this is simply to assign the
value at the point you define the variable in the class. (Notice you cannot do
this in C++, although C++ novices always try.) Here the field definitions in
class Measurement are changed to provide initial values:
|
 |
Comment peut-on donner une valeur initiale à une variable ? Une
manière directe de le faire est la simple affectation au moment de la définition de la variable
dans la classe (note : il n'est pas possible de le faire en C++ bien que tous les débutants
s'y essayent). Les définitions des champs de la classe Measurement sont modifiées
ici pour fournir des valeurs initiales :
|
 |
 |
 |
class Measurement { boolean b = true; char c = 'x'; byte B = 47; short s = 0xff; int i = 999; long l = 1; float f = 3.14f; double d = 3.14159; //. . .
|
 |
class Measurement { boolean b = true; char c = 'x'; byte B = 47; short s = 0xff; int i = 999; long l = 1; float f = 3.14f; double d = 3.14159; //. . .
|
 |
 |
 |
You can also initialize nonprimitive
objects in this same way. If Depth is a class, you can insert a variable
and initialize it like so:
|
 |
On peut initialiser des objets de type non-primitif de la même manière. Si
Depth (NDT : « profondeur ») est une classe, on peut ajouter une variable et
l'initialiser de cette façon :
|
 |
 |
 |
class Measurement { Depth o = new Depth(); boolean b = true; // . . .
|
 |
class Measurement { Depth o = new Depth(); boolean b = true; // . . .
|
 |
 |
 |
If you haven’t given o an
initial value and you try to use it anyway, you’ll get a run-time error
called an exception (covered in Chapter 10).
|
 |
Si o ne reçoit pas de valeur initiale et que l'on essaye
de l'utiliser malgré tout, on obtient une erreur à l'exécution appelée exception
(explications au chapitre 10).
|
 |
 |
 |
You can even call a method to provide an
initialization value:
|
 |
Il est même possible d'appeler une méthode pour fournir une valeur
d'initialisation :
|
 |
 |
 |
class CInit { int i = f(); //... }
|
 |
class CInit { int i = f(); //... }
|
 |
 |
 |
This method can have arguments, of
course, but those arguments cannot be other class members that haven’t
been initialized yet. Thus, you can do this:
|
 |
Bien sûr cette méthode peut avoir des arguments, mais ceux-ci ne peuvent
pas être d'autres membres non encore initialisés, de la classe. Par conséquent ce code est valide
:
|
 |
 |
 |
class CInit { int i = f(); int j = g(i); //... }
|
 |
class CInit { int i = f(); int j = g(i); //... }
|
 |
 |
 |
But you cannot do this:
|
 |
Mais pas celui-ci :
|
 |
 |
 |
class CInit { int j = g(i); int i = f(); //... }
|
 |
class CInit { int j = g(i); int i = f(); //... }
|
 |
 |
 |
This is one place in which the compiler,
appropriately, does complain about
forward referencing, since this
has to do with the order of initialization and not the way the program is
compiled.
|
 |
C'est un des endroits où le compilateur se plaint avec raison du
forward referencing (référence à un objet déclaré plus loin dans le code), car il s'agit d'une
question d'ordre d'initialisation et non pas de la façon dont le programme est compilé.
|
 |
 |
 |
This approach to initialization is simple
and straightforward. It has the limitation that every object of type
Measurement will get these same initialization values. Sometimes this is
exactly what you need, but at other times you need more
flexibility.
|
 |
Cette approche par rapport à l'initialisation est très simple. Elle est
également limitée dans le sens où chaque objet de type Measurement aura
les mêmes valeurs d'initialisation. Quelquefois c'est exactement ce dont on a besoin, mais d'autres
fois un peu plus de flexibilité serait nécessaire.
|
 |
 |
 |
Constructor initialization
|
 |
Initialisation par constructeur
|
 |
 |
 |
The constructor can be used to perform
initialization, and this gives you greater flexibility in your programming since
you can call methods and perform actions at run-time to determine the initial
values. There’s one thing to keep in mind, however: you aren’t
precluding the automatic initialization, which happens before the constructor is
entered. So, for example, if you say:
|
 |
On peut utiliser le constructeur pour effectuer les initialisations. Cela
apporte plus de flexibilité pour le programmeur car il est possible d'appeler des méthodes et
effectuer des actions à l'exécution pour déterminer les valeurs initiales. Cependant il y a une
chose à se rappeler : cela ne remplace pas l'initialisation automatique qui est faite avant
l'exécution du constructeur. Donc par exemple :
|
 |
 |
 |
class Counter { int i; Counter() { i = 7; } // . . .
|
 |
class Counter { int i; Counter() { i = 7; } // . . .
|
 |
 |
 |
then i will first be initialized
to 0, then to 7. This is true with all the primitive types and with object
references, including those that are given explicit initialization at the point
of definition. For this reason, the compiler doesn’t try to force you to
initialize elements in the constructor at any particular place, or before they
are used—initialization is already
guaranteed[30].
|
 |
Dans ce cas, i sera d'abord initialisé à 0 puis à 7. C'est
ce qui ce passe pour tous les types primitifs et les références sur objet, même pour ceux qui ont
été initialisés explicitement au moment de leur définition. Pour cette raison, le compilateur ne
force pas l'utilisateur à initialiser les éléments dans le constructeur à un endroit donné, ni
avant leur utilisation : l'initialisation est toujours garantie [30].
|
 |
 |
 |
Order of initialization
|
 |
Ordre d'initialisation
|
 |
 |
 |
Within a class, the order of
initialization is determined by the order that the variables are defined within
the class. The variable definitions may be scattered throughout and in between
method definitions, but the variables are initialized before any methods can be
called—even the constructor. For example:
|
 |
Dans une classe, l'ordre d'initialisation est déterminé par l'ordre dans
lequel les variables sont definies. Les définitions de variables peuvent être disséminées n'importe
où et même entre les définitions des méthodes, mais elles sont initialisées avant tout appel à une
méthode, même le constructeur. Par exemple :
|
 |
 |
 |
//: c04:OrderOfInitialization.java // Demonstrates initialization order.
// When the constructor is called to create a // Tag object, you'll see a message: class Tag { Tag(int marker) { System.out.println("Tag(" + marker + ")"); } }
class Card { Tag t1 = new Tag(1); // Before constructor Card() { // Indicate we're in the constructor: System.out.println("Card()"); t3 = new Tag(33); // Reinitialize t3 } Tag t2 = new Tag(2); // After constructor void f() { System.out.println("f()"); } Tag t3 = new Tag(3); // At end }
public class OrderOfInitialization { public static void main(String[] args) { Card t = new Card(); t.f(); // Shows that construction is done } } ///:~
|
 |
//: c04:OrderOfInitialization.java // Montre l'ordre d'initialisation.
// Quand le constructeur est appelé pour créer // un objet Tag, un message s'affichera : class Tag { Tag(int marker) { System.out.println("Tag(" + marker + ")"); } }
class Card { Tag t1 = new Tag(1); // Avant le constructeur Card() { // Montre que l'on est dans le constructeur : System.out.println("Card()"); t3 = new Tag(33); // Réinitialisation de t3 } Tag t2 = new Tag(2); // Après le constructeur void f() { System.out.println("f()"); } Tag t3 = new Tag(3); // la fin }
public class OrderOfInitialization { public static void main(String[] args) { Card t = new Card(); t.f(); // Montre que la construction a été effectuée } } ///:~
|
 |
 |
 |
In Card, the definitions of the
Tag objects are intentionally scattered about to prove that they’ll
all get initialized before the constructor is entered or anything else can
happen. In addition, t3 is reinitialized inside the constructor. The
output is:
|
 |
Dans la classe Card, les définitions des objets
Tag sont intentionnellement dispersées pour prouver que ces objets seront tous
initialisés avant toute action (y compris l'appel du constructeur). De plus, t3
est réinitialisé dans le constructeur. La sortie-écran est la suivante :
|
 |
 |
 |
Tag(1) Tag(2) Tag(3) Card() Tag(33) f()
|
 |
Tag(1) Tag(2) Tag(3) Card() Tag(33) f()
|
 |
 |
 |
Thus, the t3 reference gets
initialized twice, once before and once during the constructor call. (The first
object is dropped, so it can be garbage-collected later.) This might not seem
efficient at first, but it guarantees proper initialization—what would
happen if an overloaded constructor were defined that did not initialize
t3 and there wasn’t a “default” initialization for
t3 in its definition?
|
 |
La référence sur t3 est donc initialisée deux fois, une
fois avant et une fois pendant l'appel au constructeur (on jette le premier objet pour qu'il soit
récupéré par le ramasse-miettes plus tard). A première vue, cela ne semble pas très efficace, mais
cela garantit une initialisation correcte ; que se passerait-il si l'on surchargeait le
constructeur avec un autre constructeur qui n'initialiserait pas t3 et
qu'il n'y avait pas d'initialisation « par défaut » dans la définition de
t3 ?
|
 |
 |
 |
Static data initialization
|
 |
Initialisation de données statiques
|
 |
 |
 |
When the
data is static the same
thing happens; if it’s a primitive and you don’t initialize it, it
gets the standard primitive initial values. If it’s a reference to an
object, it’s null unless you create a new object and attach your
reference to it.
|
 |
Quand les données sont statiques (static) la même chose se
passe ; s'il s'agit d'une donnée de type primitif et qu'elle n'est pas initialisée, la variable
reçoit une valeur initiale standard. Si c'est une référence sur un objet, c'est la valeur
null qui est utilisée à moins qu'un nouvel objet ne soit créé et sa référence
donnée comme valeur à la variable.
|
 |
 |
 |
If you want to place initialization at
the point of definition, it looks the same as for non-statics.
There’s only a single piece of storage for a static, regardless of
how many objects are created. But the question arises of when the static
storage gets initialized. An example makes this question clear:
|
 |
Pour une initialisation à l'endroit de la définition, les mêmes règles que
pour les variables non-statiques sont appliquées. Il n'y a qu'une seule version (une seule zone
mémoire) pour une variable statique quel que soit le nombre d'objets créés. Mais une question se
pose lorsque cette zone statique est initialisée. Un exemple va rendre cette question claire
:
|
 |
 |
 |
//: c04:StaticInitialization.java // Specifying initial values in a // class definition.
class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
class Table { static Bowl b1 = new Bowl(1); Table() { System.out.println("Table()"); b2.f(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } static Bowl b2 = new Bowl(2); }
class Cupboard { Bowl b3 = new Bowl(3); static Bowl b4 = new Bowl(4); Cupboard() { System.out.println("Cupboard()"); b4.f(2); } void f3(int marker) { System.out.println("f3(" + marker + ")"); } static Bowl b5 = new Bowl(5); }
public class StaticInitialization { public static void main(String[] args) { System.out.println( "Creating new Cupboard() in main"); new Cupboard(); System.out.println( "Creating new Cupboard() in main"); new Cupboard(); t2.f2(1); t3.f3(1); } static Table t2 = new Table(); static Cupboard t3 = new Cupboard(); } ///:~
|
 |
//: c04:StaticInitialization.java // Préciser des valeurs initiales dans une // définition de classe.
class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
class Table { static Bowl b1 = new Bowl(1); Table() { System.out.println("Table()"); b2.f(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } static Bowl b2 = new Bowl(2); }
class Cupboard { Bowl b3 = new Bowl(3); static Bowl b4 = new Bowl(4); Cupboard() { System.out.println("Cupboard()"); b4.f(2); } void f3(int marker) { System.out.println("f3(" + marker + ")"); } static Bowl b5 = new Bowl(5); }
public class StaticInitialization { public static void main(String[] args) { System.out.println( "Creating new Cupboard() in main"); new Cupboard(); System.out.println( "Creating new Cupboard() in main"); new Cupboard(); t2.f2(1); t3.f3(1); } static Table t2 = new Table(); static Cupboard t3 = new Cupboard(); } ///:~
|
 |
 |
 |
Bowl allows you to view the
creation of a class, and Table and Cupboard create static
members of Bowl scattered through their class definitions. Note that
Cupboard creates a non-static Bowl b3 prior to the
static definitions. The output shows what happens:
|
 |
Bowl permet de visionner la création d'une classe.
Table, ainsi que Cupboard, créent des membres
static de Bowl partout au travers de leur définition de classe.
Il est à noter que Cupboard crée un Bowl b3
non-statique avant les définitions statiques. La sortie montre ce
qui se passe :
|
 |
 |
 |
Bowl(1) Bowl(2) Table() f(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) f2(1) f3(1)
|
 |
Bowl(1) Bowl(2) Table() f(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) f2(1) f3(1)
|
 |
 |
 |
The static initialization occurs
only if it’s necessary. If you don’t create a Table object
and you never refer to Table.b1 or Table.b2, the static Bowl b1
and b2 will never be created. However, they are initialized only when
the first Table object is created (or the first static
access occurs). After that, the static objects are not
reinitialized.
|
 |
L'initialisation statique intervient seulement si c'est
nécessaire. Si on ne crée jamais d'objets Table et que Table.b1
ou Table.b2 ne sont jamais référencés, les membres statiques Bowl
b1 et b2 ne seront jamais créés. Cependant, ils ne sont initialisés que
lorsque le premier objet Table est créé (ou le premier accès
statique est effectué). Après cela, les objets statiques ne sont
pas réinitialisés.
|
 |
 |
 |
The order of initialization is
statics first, if they haven’t already been initialized by a
previous object creation, and then the non-static objects. You can see
the evidence of this in the output.
|
 |
Dans l'ordre d'initialisation, les membres static viennent
en premier, s'ils n'avaient pas déjà été initialisés par une précédente création d'objet, les
objets non static sont traités. On peut le voir clairement dans la sortie du
programme.
|
 |
 |
 |
It’s helpful to summarize the
process of creating an object.
Consider a class called Dog:
|
 |
Il peut être utile de résumer le processus de
création d'un objet. Considérons une classe appelée Dog :
|
 |
 |
 |
- The first time an object
of type Dog is created, or the first time a static method
or static field of class Dog is accessed, the Java interpreter
must locate Dog.class, which it does by searching through the
classpath.
- As
Dog.class is loaded (creating a Class object, which you’ll
learn about later), all of its static initializers are run. Thus,
static initialization takes place only once, as the Class object
is loaded for the first
time.
- When you
create a new Dog( ), the construction process for a Dog
object first allocates enough storage for a Dog object on the
heap.
- This storage
is wiped to zero, automatically setting all the primitives in that Dog
object to their default values (zero for numbers and the equivalent for
boolean and char) and the references to
null.
- Any
initializations that occur at the point of field definition are
executed.
- Constructors
are executed. As you shall see in Chapter 6, this might actually involve a fair
amount of activity, especially when inheritance is
involved.
|
 |
- La première fois qu'un objet de type Dog est créé,
ou la première fois qu'on utilise une méthode déclarée static ou un champ
static de la classe Dog, l'interprèteur Java doit localiser
Dog.class, ce qu'il fait en cherchant dans le classpath ;
- Au moment où Dog.class est chargée (créant un objet
Class, que nous verrons plus tard), toutes les fonctions d'initialisation
statiques sont exécutées. Par conséquent, l'initialisation
statique n'arrive qu'une fois, au premier chargement de l'objet
Class ;
- Lorsque l'on exécute new Dog( ) pour créer un nouvel
objet de type Dog, le processus de construction commence par allouer suffisamment
d'espace mémoire sur le tas pour contenir un objet Dog ;
- Cet espace est mis à zéro, donnant automatiquement à tous les membres de
type primitif dans cet objet Dog leurs valeurs par défaut (zéro pour les nombres
et l'équivalent pour les boolean et les char) et aux références
la valeur null ;
- Toute initialisation effectuée au moment de la définition des champs est
exécutée ;
- Les constructeurs sont exécutés. Comme nous le verrons au chapitre 6, ceci
peut en fait déclencher beaucoup d'activité, surtout lorsqu'il y a de l'héritage.
|
 |
 |
 |
Explicit static initialization
|
 |
Initialisation statique explicite
|
 |
 |
 |
Java allows you to group other
static initializations inside a special
“static construction
clause” (sometimes called a static block)
in a class. It looks like this:
|
 |
Java permet au programmeur de grouper toute autre initialisation statique
dans une « clause de construction » static (quelquefois appelé bloc
statique) dans une classe. Cela ressemble à ceci :
|
 |
 |
 |
class Spoon { static int i; static { i = 47; } // . . .
|
 |
class Spoon { static int i; static { i = 47; } // . . .
|
 |
 |
 |
It appears to be a method, but it’s
just the static keyword followed by a method body. This code, like other
static initializations, is executed only once, the first time you make an
object of that class or the first time you access a static member
of that class (even if you never make an object of that class). For
example:
|
 |
On dirait une méthode, mais il s'agit simplement du mot-clé
static suivi d'un corps de méthode. Ce code, comme les autres initialisations
statiques, est exécuté une seule fois, à la création du premier objet de cette classe ou
au premier accès à un membre déclaré static de cette classe (même si on ne crée
jamais d'objet de cette classe). Par exemple :
|
 |
 |
 |
//: c04:ExplicitStatic.java // Explicit static initialization // with the "static" clause.
class Cup { Cup(int marker) { System.out.println("Cup(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
class Cups { static Cup c1; static Cup c2; static { c1 = new Cup(1); c2 = new Cup(2); } Cups() { System.out.println("Cups()"); } }
public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); Cups.c1.f(99); // (1) } // static Cups x = new Cups(); // (2) // static Cups y = new Cups(); // (2) } ///:~
|
 |
//: c04:ExplicitStatic.java // Initialisation statique explicite // avec l'instruction "static".
class Cup { Cup(int marker) { System.out.println("Cup(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
class Cups { static Cup c1; static Cup c2; static { c1 = new Cup(1); c2 = new Cup(2); } Cups() { System.out.println("Cups()"); } }
public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); Cups.c1.f(99); // (1) } // static Cups x = new Cups(); // (2) // static Cups y = new Cups(); // (2) } ///:~
|
 |
 |
 |
The static initializers for
Cups run when either the access of the static object c1
occurs on the line marked (1), or if line (1) is commented out and the lines
marked (2) are uncommented. If both (1) and (2) are commented out, the
static initialization for Cups never occurs. Also, it
doesn’t matter if one or both of the lines marked (2) are uncommented; the
static initialization only occurs once.
|
 |
Les instructions statiques d'initialisation pour Cups sont
exécutées soit quand l'accès à l'objet static c1 intervient à la
ligne (1), soit si la ligne (1) est mise en commentaire et les lignes (2) ne le sont pas. Si (1) et
(2) sont en commentaire, l'initialisation static pour Cups
n'intervient jamais. De plus, que l'on enlève les commentaires pour les deux lignes (2) ou pour une
seule n'a aucune importance : l'initialisation statique n'est effectuée qu'une seule
fois.
|
 |
 |
 |
Non-static instance
initialization
|
 |
Initialisation d'instance non statique
|
 |
 |
 |
Java provides a similar syntax for
initializing non-static variables for each object. Here’s an
example:
|
 |
Java offre une syntaxe similaire pour initialiser les variables non
static pour chaque objet. Voici un exemple :
|
 |
 |
 |
//: c04:Mugs.java // Java "Instance Initialization."
class Mug { Mug(int marker) { System.out.println("Mug(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
public class Mugs { Mug c1; Mug c2; { c1 = new Mug(1); c2 = new Mug(2); System.out.println("c1 & c2 initialized"); } Mugs() { System.out.println("Mugs()"); } public static void main(String[] args) { System.out.println("Inside main()"); Mugs x = new Mugs(); } } ///:~
|
 |
//: c04:Mugs.java // Java "Instance Initialization." (Initialisation d'instance de Java)
class Mug { Mug(int marker) { System.out.println("Mug(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
public class Mugs { Mug c1; Mug c2; { c1 = new Mug(1); c2 = new Mug(2); System.out.println("c1 & c2 initialized"); } Mugs() { System.out.println("Mugs()"); } public static void main(String[] args) { System.out.println("Inside main()"); Mugs x = new Mugs(); } } ///:~
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |