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.
static
.Math
et Integer
de Java.À la fin de cette leçon vous devrez être en mesure de :
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.
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)
.
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.
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 :
main
est statique etmain
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.
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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();
}
}
main
et un objet pour la classeCas 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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();
}
}
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.
static
pour exister même s’il n’y a aucun objet.private
), on ajoute un accesseur statique pour le lire.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
@startuml Thing
!theme amiga
class Thing {
- count = 0 : {static} int
- name : String
- id : int
+ Thing(String name)
+ count() : {static} int
+ toString() : String
}
@enduml
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.