Les modificateurs non-accès en Java
Utilisez les modificateurs non-accès Java — static, final, abstract, synchronized, transient, volatile — et ce que chacun contrôle.
Les modificateurs d'accès Java — public, protected, private — contrôlent qui peut voir un membre. Les modificateurs non-accès contrôlent comment il se comporte. Ce sont quelques mots-clés qui changent la propriété, la mutabilité, le multithreading, la sérialisation et quelques autres aspects. Ce chapitre fait office de carte ; chaque modificateur dispose d'un chapitre ou d'une section plus complète ailleurs.
La liste complète
| Modificateur | S'applique à | Ce qu'il fait |
|---|---|---|
static | champs, méthodes, classes imbriquées, blocs | Appartient à la classe, pas aux instances |
final | classes, méthodes, champs, paramètres, variables locales | Ne peut pas être réassigné/surchargé/étendu |
abstract | classes, méthodes | Pas de corps / ne peut pas être instancié ; doit être implémenté par une sous-classe |
synchronized | méthodes, blocs | Un seul thread à la fois peut l'exécuter sur un verrou donné |
volatile | champs | Les lectures/écritures ne sont pas mises en cache dans la mémoire locale du thread |
transient | champs | Ignoré par la sérialisation par défaut |
native | méthodes | L'implémentation réside dans du code non-Java (généralement C/C++) |
strictfp | classes, méthodes | Force un comportement flottant IEEE-754 strict (principalement historique) |
default | méthodes d'interface | Fournit un corps par défaut dans une interface |
sealed / non-sealed | classes, interfaces | Restreint les classes qui peuvent étendre (Java 17+) |
Vous rencontrerez constamment static, final, abstract et default. Les autres n'apparaissent que lorsque leur problème se pose.
static — appartient à la classe
Un membre static est associé à la classe elle-même, et non à une instance particulière :
public class Counter {
int instanceCount; // one per Counter object
static int classCount; // one shared by everyone
}static est si courant qu'il possède son propre chapitre — voir java-static.
final — ne peut pas changer
final signifie « cette liaison est fixée une fois définie ». Il s'applique à plusieurs choses différentes :
final int MAX = 100; // local variable cannot be reassigned
public final class Money {} // class cannot be extended
public final void close() {} // method cannot be overridden
private final int balance; // field assigned once, then immutablefinal est le fondement des constantes (static final), des objets immuables et d'une conception d'héritage sûre. Traitement complet dans java-final.
abstract — n'a pas de corps, doit être rempli
abstract appliqué à une classe signifie « vous ne pouvez pas instancier cela directement — seulement les sous-classes. » Appliqué à une méthode, cela signifie « pas de corps ici — chaque sous-classe concrète doit en fournir un » :
public abstract class Shape {
public abstract double area(); // no body
}
public class Circle extends Shape {
double r;
public double area() { return Math.PI * r * r; }
}new Shape() est une erreur de compilation ; new Circle() fonctionne. Traité dans classes abstraites.
synchronized — un thread à la fois
Lorsque deux threads peuvent appeler la même méthode sur le même objet, marquer la méthode synchronized garantit qu'un seul s'exécute à la fois :
public synchronized void deposit(int amount) {
balance += amount;
}C'est la forme la plus simple de verrouillage. Il y a une section entière sur la concurrence plus loin dans le livre ; pour l'instant, reconnaissez que le mot-clé existe et ce qu'il fait globalement. Voir synchronisation pour l'histoire complète.
volatile — visible entre les threads
Sans volatile, les threads sont autorisés à mettre en cache la valeur d'un champ. Les lectures dans un thread pourraient ne jamais voir les écritures d'un autre :
private volatile boolean stopped = false;volatile force chaque lecture à venir de la mémoire principale et chaque écriture à y aller. C'est le cousin léger de synchronized pour les champs indicateurs simples — voir volatile pour les détails du modèle mémoire.
transient — ignoré lors de la sérialisation
La sérialisation d'objets intégrée de Java (Serializable) écrit tous les champs par défaut. transient dit « n'inclus pas celui-ci » — généralement utilisé pour les caches, les valeurs calculées ou les choses qui n'ont pas de sens en dehors du programme en cours d'exécution :
public class Session {
String userId;
transient String passwordHash; // not serialized
}Le code moderne utilise les sérialiseurs JSON plus que Serializable, mais le mot-clé est toujours utile dans les bibliothèques qui en tiennent compte. Plus d'informations dans sérialisation.
native — implémenté ailleurs
native est pour les méthodes dont le corps est dans un autre langage (C/C++ via JNI). Vous les écrivez rarement vous-même ; vous ne les voyez que dans les bibliothèques de bas niveau :
public native int currentTimeMillis();strictfp — virgule flottante stricte
À l'origine, strictfp forçait une arithmétique à virgule flottante IEEE-754 prévisible entre plateformes. À partir de Java 17, toutes les mathématiques en virgule flottante sont implicitement strictes, ce qui rend le mot-clé sans effet. Vous pouvez l'ignorer dans la plupart des cas ; il subsiste dans les bases de code plus anciennes.
default — sur les méthodes d'interface
Dans une interface, default vous permet de fournir un corps pour une méthode au lieu de la laisser abstraite :
public interface Greeter {
default String greet(String name) {
return "Hello, " + name;
}
}Sans default, une méthode d'interface n'a pas de corps et chaque classe implémentante doit écrire la sienne. Traitement complet dans méthodes par défaut.
sealed et non-sealed
Une classe sealed nomme la liste exacte des classes autorisées à l'étendre. Les sous-classes doivent ensuite choisir d'être final, sealed ou non-sealed :
public sealed class Shape permits Circle, Square { }
public final class Circle extends Shape { }
public non-sealed class Square extends Shape { }Utile pour les hiérarchies de types fermées — voir classes scellées.
Combiner les modificateurs
Vous pouvez généralement empiler les modificateurs librement, dans cet ordre conventionnel :
public static final int MAX = 100;
private static volatile int counter;
protected abstract void onInit();Certaines combinaisons sont illégales : une méthode ne peut pas être à la fois abstract et final, à la fois abstract et private, ou à la fois abstract et static. Le compilateur vous le dira lorsque vous aurez franchi une limite.
Un exemple concret
Et ensuite
Les deux prochains chapitres approfondissent les deux modificateurs que vous utiliserez le plus souvent : static pour les membres au niveau de la classe, puis final pour l'immuabilité. Lisez-les dans l'ordre.