W3docs

Le mot-clé static en Java

Déclarez des membres de classe en Java avec static — champs statiques, méthodes, blocs et classes imbriquées statiques.

static est le mot-clé qui fait passer un membre de classe de « un par instance » à « un par classe ». Un champ statique possède une seule copie partagée par tous les objets. Une méthode statique appartient à la classe elle-même et s'exécute sans aucune instance. Un bloc statique s'exécute une seule fois, lors du premier chargement de la classe. Une classe imbriquée statique vit à l'intérieur d'une autre classe sans avoir besoin d'un objet englobant.

La règle de base : les membres static n'ont pas de this. Tout le reste de leur comportement en découle.

Champs statiques

Un champ statique est déclaré avec static dans le corps de la classe. Il n'en existe qu'une seule copie, quel que soit le nombre d'instances :

public class Counter {
  static int total;       // one Counter.total for everybody
  int count;              // each Counter has its own count
}

Counter a = new Counter();   a.count++;   Counter.total++;
Counter b = new Counter();   b.count++;   Counter.total++;

System.out.println(a.count);          // 1
System.out.println(b.count);          // 1
System.out.println(Counter.total);    // 2

Accédez à un champ statique via le nom de la classe (Counter.total) — c'est la forme canonique. Java autorise aussi a.total car a est un Counter, mais tous les linters du monde signalent ce style.

Méthodes statiques

Une méthode statique appartient à la classe. Appelez-la avec NomDeClasse.méthode(...) :

public class MathUtil {
  public static int square(int n) {
    return n * n;
  }
}

int x = MathUtil.square(7);     // 49

Dans une méthode statique, il n'y a pas de this — vous ne pouvez pas lire des champs d'instance ni appeler des méthodes d'instance sans qualificateur, car il n'y a pas d'instance courante depuis laquelle les lire :

public class Counter {
  int count;
  static void reset() {
    count = 0;      // ERROR: cannot reference instance field from static context
  }
}

Vous pouvez tout de même recevoir une instance en paramètre et opérer dessus :

static void resetThis(Counter c) {
  c.count = 0;     // ok — c is a parameter, not this
}

La direction inverse fonctionne bien : une méthode d'instance peut appeler une méthode statique sans cérémonie, car la classe est toujours disponible même lorsqu'une instance existe.

Quand choisir static

Le seul critère est de savoir si le membre dépend d'un état par instance.

Dépend de this ?Utiliser
Non — calcul pur, compteur partagé, méthode factorystatic
Oui — lit ou modifie les propres champs de l'objetinstance
public static int hoursToSeconds(int h) { return h * 3600; }   // no this needed → static
public        int rentalDays()           { return days; }       // reads this.days → instance

Un symptôme courant : une méthode d'instance qui ignore this. Elle ment sur son caractère spécifique à l'instance — rendez-la static et l'appelant n'aura plus à inventer un objet rien que pour l'utiliser.

Constantes statiques

La combinaison static final est la forme standard pour les constantes :

public static final double TAX_RATE = 0.08;
public static final int    MAX_RETRIES = 3;
public static final String DEFAULT_LOCALE = "en";

Par convention, les constantes sont nommées en UPPER_SNAKE_CASE. Elles sont intégrées au moment de la compilation lorsque la valeur est primitive ou un littéral String, ce qui les rend aussi rapides qu'un littéral au point d'appel.

Blocs statiques

Un bloc static { ... } s'exécute une seule fois, lors du premier chargement de la classe dans la JVM. Utilisez-le pour une initialisation unique de champs statiques qui nécessitent plus qu'une simple expression :

public class Lookup {
  static final Map<String, Integer> WEEKDAYS = new HashMap<>();
  static {
    WEEKDAYS.put("Mon", 1);
    WEEKDAYS.put("Tue", 2);
    WEEKDAYS.put("Wed", 3);
    WEEKDAYS.put("Thu", 4);
    WEEKDAYS.put("Fri", 5);
    WEEKDAYS.put("Sat", 6);
    WEEKDAYS.put("Sun", 7);
  }
}

Les blocs statiques sont puissants mais faciles à surutiliser. Préférez un simple initialiseur de champ lorsqu'une expression suffit.

Les champs statiques et les blocs statiques s'exécutent de haut en bas dans l'ordre où ils apparaissent dans le source. Si un initialiseur accède à un champ (via une méthode) avant que la propre ligne de ce champ ait été exécutée, il voit la valeur par défaut (0, false ou null) — l'ordre a donc de l'importance :

public class Order {
  static int a = compute();          // runs first; b is still 0 → a becomes 1
  static int b = 10;                 // runs second
  static int compute() { return b + 1; }
}
// Order.a == 1, Order.b == 10

(Lire b directement sur cette première ligne — static int a = b + 1; — constitue en revanche une erreur de compilation « illegal forward reference » ; seul le chemin indirect via une méthode expose la valeur par défaut.)

Classes imbriquées statiques

Une classe déclarée static à l'intérieur d'une autre classe est une classe imbriquée statique. Contrairement à une classe interne non statique, elle ne porte pas de référence implicite à une instance de la classe externe :

public class Outer {
  static class Inner {           // does not need an Outer instance
    void hello() { System.out.println("hi"); }
  }
}

Outer.Inner i = new Outer.Inner();   // create directly
i.hello();

C'est ainsi que nous avons enveloppé des classes auxiliaires dans le même fichier que main dans des blocs static class Foo {...} précédents — main est statique, nous devons donc que la classe auxiliaire soit elle aussi statique pour pouvoir l'instancier sans une instance Outer englobante. Le chapitre sur les classes imbriquées couvre les quatre variantes.

static n'est pas « le constructeur »

Les débutants confondent parfois « static = s'exécute une fois » avec « static = s'exécute à la création d'un objet ». L'initialisation statique se produit une fois par classe, et non une fois par objet. Le constructeur s'exécute une fois par objet. Ce sont des mécanismes distincts qui se déclenchent dans des situations différentes.

Membres statiques dans les interfaces

Les interfaces peuvent également avoir des méthodes static. Elles se comportent de la même façon que les membres statiques de classe — appelez-les avec NomInterface.méthode(...) :

public interface Path {
  static Path of(String s) { return new SimplePath(s); }
}

Path p = Path.of("/tmp/foo");

Le chapitre sur les interfaces explique quand c'est une bonne idée (méthodes factory sur l'interface elle-même).

Un exemple complet

java— editable, runs on the server

Ce programme affiche :

#1  apple   base=0.50 USD,  with tax=0.54
#2  bread   base=2.40 USD,  with tax=2.59
#3  butter  base=3.10 USD,  with tax=3.35
Total items ever created: 3

Remarquez comment l'exemple mélange les quatre variantes : les constantes et la table de correspondance sont remplies avant qu'aucun Item n'existe, chaque Item conserve son propre name et basePrice, et le seul champ partagé itemsCreated distribue l'id courant.

La suite

static vous permet de dire qui possède un membre. Le prochain compagnon est final, qui vous permet de dire s'il peut changer. Ensemble, static final est la forme standard pour les constantes ; seul, final façonne l'héritage et la conception immuable. Continuez vers java-final.

Pratique

Pratique
Pourquoi une méthode statique génère-t-elle une erreur de compilation si elle tente de lire un champ d'instance par son nom brut ?
Pourquoi une méthode statique génère-t-elle une erreur de compilation si elle tente de lire un champ d'instance par son nom brut ?
Was this page helpful?