Keyboard shortcuts

Touchez ← ou → pour naviguer les chapitres

Touchez S ou / pour chercher dans le livre

Touchez ? pour afficher ce message

Touchez Esc pour masquer ce message

Accueil > Classes et objets >

📚 Membres statiques

Survol et attentes

Plusieurs mot-clĂ©s Java dans la signature classique public static void main(String[] args) ont maintenant Ă©tĂ© dĂ©mystifiĂ©s, D’abord on a les types void et String[]. Plus rĂ©cemment on a vue public et private qui dĂ©terminent la visibilitĂ© d’une classe ou de ses membres Ă  l’extĂ©rieur de la classe. Il ne reste que static Ă  expliquer.

Définitions
Membre dynamique
Un membre d’une classe (attribut ou mĂ©thode) qui est associĂ© Ă  une instance de la classe, soit aux objets créés et dĂ©truits durant l’exĂ©cution du programme.
Membre statique
Un membre d’une classe (attribut ou mĂ©thode) qui est associĂ© Ă  la classe elle-mĂȘme et non aux objets créés Ă  partir de la classe. Les membres statiques sont disponibles mĂȘme si aucun objet n’est créé. Ces membres sont dĂ©clarĂ©s avec le mot-clĂ© static.
Classe utilitaire
Une classe qui contient exclusivement des membres statiques pour effectuer des tùches spécifiques. Les membres statiques sont accessibles directement en utilisant le nom de la classe, comme avec les classes Math et Integer de Java.
ÉlĂ©ments statiques et dynamiques
En gĂ©nĂ©ral, les parties d’un programme qui sont connues explicitement au moment de la compilation sont dites “statiques”. Les autres Ă©lĂ©ments sont “dynamiques”, connus seulement au moment de l’exĂ©cution.
  • Les dĂ©clarations de classes sont statiques.
  • Les objets et les variables locales sont dynamiques.
  • Dans certains langages oĂč les dĂ©finitions de fonctions et des variables peuvent exister en dehors des classes (la plupart des langages Ă  part Java), ces fonctions et variables globales sont aussi statiques.
  • Les langages de programmation qui exigent la dĂ©claration de types pour les variables et fonctions sont dits “statiquement typĂ©s”; les autres sont dits “dynamiquement typĂ©s” car le type doit ĂȘtre dĂ©terminĂ© au moment de l’exĂ©cution.

Objectifs d’apprentissage

À la fin de cette leçon vous devrez ĂȘtre en mesure de :

  • DĂ©crire la diffĂ©rence entre les membres statiques et dynamiques d’une classe.
  • Distinguer l’utilisation d’un membre statique et l’utilisation d’un membre dynamique dans divers extraits de code, comme la dĂ©claration de membres d’une classe ou l’utilisation de ces membres dans un algorithme.

CritĂšres de succĂšs

  • Je suis capable d’utiliser des membres statiques dans mes objets ou les membres statiques de plusieurs classes utilitaires de Java.

Dynamique versus statique

Dans la programmation, le terme “statique” fait rĂ©fĂ©rence au stade de compilation/interprĂ©tation du projet. Si les types sont connus au moment de la compilation, un langage de programmation est dit “statiquement typĂ©â€. Java et C++ sont des langages statiquement typĂ©s parce qu’on doit dĂ©clarer les types des variables et fonctions dans le code. De mĂȘme, si des variables ou des mĂ©thodes opĂšrent directement sur la classe (et non sur une instance de la classe), elles sont dites “statiques” parce que la dĂ©finition de la classe est connue au moment de la compilation, contrairement aux instances de la classe (les objets) qui sont crĂ©es durant l’exĂ©cution du programme.

De l’autre cĂŽtĂ©, tout ce qui est créé ou dĂ©terminĂ© au moment de l’exĂ©cution est dite “dynamique”. Par exemple, les variables locales sont dynamiques parce qu’elles sont créées et dĂ©truites Ă  chaque fois que la mĂ©thode qui les contient est appelĂ©e. Les objets sont aussi dynamiques parce qu’ils sont créés et dĂ©truits durant l’exĂ©cution du programme. Dans certains langages, la dĂ©termination du type est aussi dynamique parce que le type n’est pas dĂ©clarĂ© dans la syntaxe du langage mais seulement dĂ©terminĂ© au moment de l’exĂ©cution en fonction de l’information contenue dans la variable. Python et Javascript sont des langages dynamiquement typĂ©s.

Le mot-clé static

En Java, le mot-clĂ© static s’applique Ă  un membre d’une classe pour l’associer Ă  la classe elle-mĂȘme et non aux instances de la classe. Cela signifie que les variables et les mĂ©thodes statiques sont disponibles mĂȘme si aucun objet n’est créé Ă  partir de la classe.

On connaßt déjà quelques exemples notables dans la bibliothÚque standard de Java :

  • La classe Math contient des mĂ©thodes et constantes (variables final) statiques pour effectuer des opĂ©rations mathĂ©matiques. On les utilise en appelant Math.PI ou par exemple, Math.sqrt(16).

  • Les classes qui emballent les types primitifs (comme Integer, Double, etc.) contiennent des mĂ©thodes statiques pour convertir des chaĂźnes de caractĂšres en nombres comme Integer.parseInt("42") ou pour obtenir des informations fixes en lien avec le type, comme Double.MAX_VALUE.

  • La mĂ©thode main qui est le point d’entrĂ©e de tout programme Java. On ne dĂ©clare aucun objet pour utiliser notre programme, on passe seulement le nom de notre classe, p. ex. avec la commande java App. La machine virtuelle Java peut alors appeler directement la mĂ©thode statique avec le nom de la classe, p. ex. App.main(args).

Classes utilitaires

Les exemples comme Math et Integer sont des classes contenant exclusivement des membres publiques statiques. Ce type de classe est souvent appelĂ© une “classe utilitaire” ou “classe de service” parce qu’elle fournit des mĂ©thodes et des constantes pour effectuer des tĂąches spĂ©cifiques.

Dépendances statiques

Tout ce qu’on ajoutait comme membre dans nos classes en ICS3U - Scanner et autres variables globales, mĂ©thodes pour la dĂ©composition - devaient ĂȘtre dĂ©clarĂ©s static pour satisfaire au compilateur. C’est parce que :

  1. la méthode main est statique et
  2. on utilisait tout directement dans main sans dĂ©clarer d’objet pour notre propre classe.

La mĂ©thode main Ă©tant static signifie qu’elle ne peut pas accĂ©der Ă  des membres non statiques de la classe car ils ne sont pas créés en mĂȘme temps que la mĂ©thode main lors de la compilation. Donc tout ce qu’on voulait utiliser dans main devait aussi ĂȘtre static pour ĂȘtre accessible.

Classe ou tout est statique Ă  cause de main

Cas typique de programme Java avant d’apprendre les objets. Tout est statique parce qu’on l’utilise directement dans main sans crĂ©er d’objet pour la classe.

public class Main {

    static int x = 42;

    static void doStuff() {
        System.out.println("On bosse");
    }

    public static void main(String[] args) {
        // utilise directement les attributs et méthodes statiques
        System.out.println(x);
        doStuff();
    }

}

Classe avec main et un objet pour la classe

Cas hybride oĂč les fonctions “dĂ©finition d’un objet” et “pilote du programme” sont accomplies par la mĂȘme classe : on a une mĂ©thode main mais aussi des attributs et mĂ©thodes d’objet. Ce type de classe n’est pas souvent utilisĂ© non plus. On utilise plutĂŽt une classe pour dĂ©clarer des objets et une autre pour le pilote.

public class Main {

    int x = 42;

    void doStuff() {
        System.out.println("On bosse");
    }

    public static void main(String[] args) {
        // Crée un objet de la classe Main
        Main m = new Main();
        // utilise les attributs et méthodes de l'objet
        System.out.println(m.x);
        m.doStuff();
    }

}

Mélanger des membres statiques et dynamiques

Il est possible qu’une classe objet dĂ©clare quelques attributs ou mĂ©thodes statiques en plus de dĂ©clarer des attributs et mĂ©thodes pour les instances de la classe.

L’exemple le plus courant est un attribut qui compte le nombre d’objets créés Ă  partir de la classe, ou qui assure l’assignation d’un numĂ©ro d’identitĂ© unique Ă  chaque objet, oĂč les deux.

  1. Cet attribut est dĂ©clarĂ© static pour exister mĂȘme s’il n’y a aucun objet.
  2. On l’initialise Ă  0 dans la dĂ©claration.
  3. On l’incrĂ©mente dans le constructeur de la classe qui est appelĂ© chaque fois qu’un objet est créé.
  4. Si on le cache (visibilité private), on ajoute un accesseur statique pour le lire.

Classe objet

public class Thing {
    // variable de classe
    private static int count = 0;

    // variables d'instance
    private String name;
    private int id;

    public Thing(String name) {
        this.name = name;
        this.id = count; // assigne un nombre unique Ă  chaque objet
        count++; // incrémente la variable de classe
    }

    // accesseur statique
    public static int count() {
        return count;
    }

    // ... accesseurs, mutateurs, etc. pour les variables d'instance

    @Override
    public String toString() {
        return String.format("Thing %d s'appelle %s\n", id, name);
    }

}

Classe pilote

public class Main {

    public static void main(String[] args) {
        Thing t1 = new Thing("Antoinette");
        Thing t2 = new Thing("Berenice");
        Thing t3 = new Thing("Constantin");

        // appels de méthodes d'instance, sur les objets individuels
        String rollCall  = t1.toString() + t2.toString() + t3.toString();
        System.out.println(rollCall);

        // appelle statique, sur la classe Thing
        System.out.printf("Il existe %d Thing.\n", Thing.count());
    }

}

Voici le diagramme UML pour la classe Thing. Notez que le mot-clĂ© static est utilisĂ© dans le texte entre accolades pour indiquer les membres statiques et que dans l’image, ces membres sont soulignĂ©s.

@startuml Thing
!theme amiga

class Thing {
    - count = 0 : {static} int
    - name : String
    - id : int
    + Thing(String name)
    + count() : {static} int
    + toString() : String
}

@enduml

Thing

Exercices

Pratique

Ajustez le code de votre objet simple pour ajouter un compteur statique privĂ© ainsi qu’un accesseur statique public pour ce compteur. Modifiez aussi le code dans la classe pilote pour afficher le nombre d’objets créés.

© 2022-2025 David Crowley