Ch. 3 — Statique, final et énumérations
Attributs et méthodes de classe, constantes final, blocs d'initialisation statiques, boîtes à outils Arrays et Collections, et les énumérations Java : de vraies classes aux instances figées.
final : la constante
Le mot-clé final verrouille une valeur : une fois initialisée, elle ne peut plus être
modifiée. Par convention, son identifiant s'écrit en majuscules. Une constante peut
être initialisée à la déclaration — ou au constructeur, ce qui laisse la souplesse d'une
valeur fixée par instance sans écrire de littéral « en dur » dans le code.
Le cours le montre sur un Disc qui calcule périmètre et aire avec un littéral 3.14
recopié dans chaque méthode : la première correction consiste à nommer la constante.
Mais en déclarant private final double PI, chaque instance de Disc crée sa propre
copie d'une valeur identique pour toutes — pas raisonnable. La suite logique est donc le
niveau classe.
Les trois combinaisons à connaître
static final: la même constante pour toutes les instances — c'est le cas des wrappers (Integer.MAX_VALUE,Boolean.TRUE,Double.MIN_VALUE) ;finalsansstatic: une constante par instance, initialisée au constructeur ;staticsansfinal: une valeur commune à toutes les instances, modifiable.
static : le niveau classe
Un attribut de classe existe en un seul exemplaire, quel que soit le nombre
d'instances — on y accède par le nom de la classe (Disc.PI), pas par une référence.
Changer Disc.PI change d'un coup l'aire calculée par tous les disques. Le cours en
donne l'usage canonique : le numéro automatique.
public class Order {
private static final String ID_PREFIX = "order@";
private static int counter = 1;
private Person client;
private String id;
public Order(Person cli) {
this.client = cli;
this.id = Order.ID_PREFIX + Order.counter++;
}
}Trois commandes créées successivement reçoivent order@1, order@2, order@3 : le
compteur est une mémoire partagée entre les instances. Quand l'initialisation exige
un traitement, elle quitte le constructeur pour un bloc statique, exécuté une seule
fois au chargement de la classe :
static final int[] VALUES;
static {
VALUES = new int[SIZE];
for (int i = 0; i < VALUES.length; i++) { VALUES[i] = i; }
}Les méthodes de classe s'invoquent sans instance (StaticExample.staticMethod()) —
main en est le cas particulier, puisqu'elle s'exécute avant tout objet. Le support
insiste : n'utilisez des attributs ou méthodes de classe que quand c'est indispensable.
Les boîtes à outils : Arrays et Collections
Une classe « boîte à outils » regroupe des traitements qui ne concernent aucune instance
en particulier : presque toutes ses méthodes sont statiques. java.util.Arrays facilite
la manipulation des tableaux — affichage, remplissage, test d'égalité, recherche, tri :
int[] tab = {1, 5, 2, 0, 7, 3};
Arrays.toString(tab); // "[1, 5, 2, 0, 7, 3]" — finie la boucle d'affichage
Arrays.fill(tab, 10); // remplissage forcé à une même valeur
int[] copy = Arrays.copyOf(tab, 10); // copie tronquée ou complétée par des zéros
Arrays.equals(tab, copy); // égalité contenu à contenu (pas de == !)
Arrays.sort(tab, 3, tab.length); // tri complet ou partiel
Arrays.binarySearch(tab, 7); // recherche dichotomiquePour les tableaux de tableaux, toString et equals ne voient que des références
([[I@4aa298b7, ...], false) : il faut les versions profondes deepToString et
deepEquals.
binarySearch exige un tableau trié
La recherche dichotomique suppose un tableau ordonné — sur un tableau non trié, le
résultat n'a pas de sens. Une valeur absente renvoie un entier négatif (-7 sur
l'exemple du cours) : à lire comme « non trouvé », pas comme une position.
L'enum : une classe aux instances figées
Un type énuméré est une classe avec un nombre prédéfini et fixe d'instances — les valeurs sont des objets, instances de la classe créée :
public enum Season { SPRING, SUMMER, FALL, WINTER }
Season s = Season.SUMMER;Chaque enum fournit d'office : name() (le nom exact de la constante), ordinal() (sa
position dans la déclaration, à partir de 0) et, côté classe, valueOf(String) et
values(). Le cours démonte le code généré par le compilateur pour bien comprendre :
une classe à constructeur privé, dont les valeurs sont des attributs static final
instanciés une fois pour toutes — impossible d'en créer d'autres. L'enum reste une vraie
classe, que l'on peut enrichir : attributs, méthodes, constructeurs paramétrés (à
condition qu'ils restent privés).
public enum Day {
MONDAY(true), TUESDAY(true), WEDNESDAY(true), THURSDAY(true),
FRIDAY(true), SATURDAY(false), SUNDAY(false);
private final boolean WORKING;
private Day(boolean value) { this.WORKING = value; }
public boolean isAWorkingDay() { return this.WORKING; }
}Les combinaisons d'ordinal() et values() font de petites mécaniques élégantes —
passer à la saison suivante : Season.values()[(index + 1) % Season.values().length].
En UML : les membres static sont soulignés, les constantes final en majuscules,
et l'enum porte le stéréotype «enum».
Quand choisir une enum ?
Dès que l'ensemble de valeurs est fermé — saisons, statuts, couleurs de carte : le compilateur vérifie l'exhaustivité des traitements, l'autocomplétion liste les valeurs, et une faute de frappe dans une chaîne devient impossible.
A retenir
finalinterdit la réaffectation ;staticplace le membre au niveau de la classe ;- numéro automatique et bloc statique : les deux idiomes
staticdu cours ; Arrays/Collections: des boîtes à outils de méthodes statiques ;- une enum est une classe enrichissable, à instances figées dès la déclaration.
Parce que le nombre d'instances est fixé par la déclaration : ce sont les
constantes listées. Un constructeur public permettrait d'en créer d'autres et
détruirait la garantie d'exhaustivité que le compilateur exploite — notamment pour
vérifier qu'un switch traite tous les cas.
Un littéral recopié à plusieurs endroits est une redondance : toute correction passe
inévitablement à côté d'une occurrence. Nommer la constante (final) centralise la
valeur, documente son rôle et rend le calcul vérifiable.
ordinal() renvoie la position de la constante dans la déclaration — utile pour
calculer la suivante ou la précédente. name() renvoie son nom exact tel qu'écrit
dans l'enum. Deux constantes peuvent avoir des ordinaux adjacents mais jamais le même
nom.
Un tableau est un objet : == compare les références, pas le contenu. Deux
tableaux de contenu identique construits séparément sont deux objets différents —
Arrays.equals compare case par case, et deepEquals descend dans les sous-tableaux.
coursOO_03.pdf
R2.01 · Cours 3 — Attributs, méthodes et classes statiques · 32 diapositives
Chargement du document…
Dernière mise à jour le
Ch. 1-2 — Bases de l'objet et références
Passer de l'impératif à l'objet en Java : classes, constructeurs, UML et conventions — puis la mécanique des références, passage par valeur, equals et encapsulation.
Ch. 4 — Encapsulation, surcharge, polymorphisme
Encapsulation par délégation et ses quatre objectifs, surcharge et chaînage de constructeurs, ArrayList face au tableau — puis la mécanique du polymorphisme : type de la référence, classe réelle et late binding.