count
est static dans la classe Counter
, tu peux référencer la variable avec l'expression suivante : Counter.count
.
Bien sûr, les modificateurs d'accès doivent également être considérés. Par exemple, les champs private
ne sont disponibles que dans la classe où ils sont déclarés, alors que les champs protected
le sont pour toutes les classes dans un package, ainsi que toutes leurs sous-classes en dehors du package.
Supposons que la classe Counter
dispose d'une méthode static increment()
dont le travail consiste à incrémenter le champ count
. Pour appeler cette méthode, tu peux utiliser Counter.increment()
. Tu n'as pas besoin de créer une instance de la classe Counter
pour accéder à un champ ou une méthode static. C'est la différence fondamentale entre les variables et méthodes static (de classe) et les variables et méthodes NON static (d'instance).
Remarque importante. N'oublie pas que les membres static de la classe appartiennent directement à la classe, et non à une instance particulière de la classe. Autrement dit, la valeur de la variable static count
sera la même pour tous les objets Counter
. Dans cet article, nous allons examiner les aspects fondamentaux de l'utilisation du modificateur static en Java, ainsi que certaines caractéristiques qui t'aideront à comprendre des concepts de programmation essentiels.Ce que tout programmeur doit savoir sur le modificateur static en Java : Méthode statique. Classe statique.
Dans cette section, nous examinons les principaux aspects de l'utilisation des méthodes, champs et classes static en Java. Commençons par les variables.Tu ne peux PAS accéder aux membres non static d'une classe dans un contexte static, comme une méthode ou un bloc static. La compilation du code ci-dessous générera une erreur :
public class Counter { private int count; public static void main(String args []) { System.out.println(count); // Compile time error } }
C'est une des erreurs les plus courantes commises par les programmeurs Java, en particulier les débutants. Comme la méthode
main
est static et que la variablecount
ne l'est pas, utiliser la méthodeprintln
au sein de la méthodemain
produira une « erreur au moment de la compilation ».Contrairement aux variables locales, les champs et méthodes static ne sont PAS
thread safe
en Java. Dans la pratique, c'est une des causes les plus fréquentes de problèmes de sécurité dans la programmation multithread. Comme chaque instance d'une classe fait référence à la même copie d'une variable static, une telle variable doit être protégée ou « verrouillée » par la classe. Par conséquent, lors de l'utilisation des variables static, tu dois t'assurer qu'elles sont correctementsynchronized
pour éviter des problèmes tels que lesrace conditions
.Les méthodes static ont un avantage pratique en cela qu'il n'y a pas besoin de créer un nouvel objet chaque fois que tu veux les appeler. Une méthode static peut être appelée en utilisant le nom de la classe qui la déclare. Voilà pourquoi ces méthodes sont parfaites pour les méthodes de
factory
etutility
. La classejava.lang.Math
en est un merveilleux exemple : presque toutes ses méthodes sont static. Les classes utilitaires de Java sont marquéesfinal
, pour une raison quelconque.Un autre point important est que vous ne pouvez pas remplacer (
@Override
) les méthodes statiques. Si vous déclarez une telle méthode dans unesubclass
, c'est-à-dire une méthode avec le même nom et la même signature, vous "cachez" simplement la méthode de lasuperclass
au lieu de la remplacer. Ce phénomène est connu sous le nommethod hiding
. Cela signifie que si une méthode static est déclarée à la fois dans la classe parent et la classe enfant, la méthode appelée sera toujours celle du type de la variable au moment de la compilation. Contrairement à ce qui arrive avec le remplacement de méthode, ces méthodes ne seront pas exécutées lors de l'exécution du programme. Prenons un exemple :class Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the parent class / static method"); } } class Car extends Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the child class / static method"); } } public class Demo { public static void main(String args []) { Vehicle v = new Car(); v.kmToMiles(10); } }
Sortie de la console :
Inside the parent class / static method
Le code démontre clairement que, malgré le fait que l'objet est de type
Car
, c'est la méthode static de la classeVehicle
qui est appelée, car la méthode a été appelée au moment de la compilation. Et note qu'il n'y a pas eu d'erreurs de compilation !Par ailleurs, en plus des classes de haut niveau, tu peux déclarer des classes static dans d'autres classes. Ces classes sont appelées
nested static classes
. Elles sont utiles pour assurer une meilleure cohésion. Un exemple frappant d'une classe static imbriquée estHashMap.Entry
, qui est une structure de données à l'intérieur d'uneHashMap
. Il est intéressant de noter que, comme les classes internes, les classes static imbriquées sont déclarées dans des fichiers .class séparés. Ainsi, si tu déclares cinq classes imbriquées dans ta classe principale, tu auras 6 fichiers avec l'extension .class. Un autre exemple est la déclaration de notreComparator
en tant que comparateur d'âge (AgeComparator
) dans la classeEmployee
.Le modificateur static peut également être utilisé dans un bloc d'initialisation static, plus connu sous le simple nom de « bloc static », qui est exécuté lorsque la classe est chargée. Si tu ne déclares pas un tel bloc, Java rassemble tous les champs static dans une même liste et les initialise lorsque la classe est chargée. Un bloc static ne peut PAS lever d'exceptions vérifiées, mais il peut lever des exceptions non vérifiées. Dans ce cas, une
ExceptionInInitializerError
se produira. Dans la pratique, toute exception qui se produit lors de l'initialisation des champs static sera enveloppée dans cette erreur en Java. C'est aussi la cause la plus commune deNoClassDefFoundError
, car la classe ne sera pas en mémoire quand elle sera référencée.Il est utile de savoir que les méthodes static sont liées au moment de la compilation, contrairement à ce qui se passe avec les méthodes virtual ou non static, qui sont liées au moment de l'exécution lorsqu'elles sont appelées sur un objet spécifique. Par conséquent, les méthodes static ne peuvent pas être remplacées en Java, car le polymorphisme ne les concerne pas au moment de l'exécution. C'est une limitation importante à prendre en compte lors de la déclaration d'une méthode static. Cela n'a de sens que lorsqu'il n'y a pas de capacité ou de besoin de remplacer la méthode dans une sous-classe. Les méthodes de fabrique et les méthodes utilitaires sont de bons exemples d'utilisation correcte du modificateur static. Joshua Bloch souligne plusieurs avantages que les méthodes de fabrique statiques ont par rapport aux constructeurs dans son livre Java efficace, une lecture incontournable pour tous les programmeurs Java.
L'initialisation est un aspect important d'un bloc static. Les champs ou variables static sont initialisés après que la classe est chargée en mémoire. L'ordre d'initialisation est de haut en bas, dans le même ordre de déclaration que dans le fichier source de la classe Java. Comme les champs static sont initialisés de manière thread-safe, ce processus est également utilisé pour implémenter le modèle de
Singleton
. Si tu n'utilises pasEnum
commeSingleton
pour une raison quelconque, tu disposes ainsi d'une bonne alternative. Mais dans ce cas, tu dois tenir compte du fait que ce n'est pas une initialisation « paresseuse ». Cela signifie que le champ static sera initialisé même AVANT que quelqu'un le « demande ». Si un objet est lourd en ressources ou rarement utilisé, l'initialiser dans un bloc static ne jouera pas en ta faveur.Au cours de la sérialisation, les champs static, comme les variables
transient
, ne sont pas sérialisés. Toutes les données enregistrées dans un champ static contiendront la valeur initiale (par défaut) après la désérialisation. Par exemple, si un champ static est unint
, sa valeur sera égale à zéro après la désérialisation. Si son type estfloat
, la valeur sera 0.0. Si le champ est unObject
, la valeur seranull
. Pour tout te dire, c'est une des questions les plus fréquemment posées au sujet de la sérialisation dans les entretiens pour des postes de développeur Java. Ne stockez pas de données d'objet essentielles dans un champ static !Enfin, nous allons parler de l'importation static. Cette utilisation du modificateur static est une variante de l'instruction
import
standard. Elle est différente en cela qu'elle te permet d'importer un ou tous les membres static de la classe. Une fois que les méthodes static sont importées, elles peuvent être consultées comme si elles avaient été déclarées dans la même classe. De même, en important des champs static, on peut y accéder sans préciser le nom de la classe. Cette fonctionnalité est apparue avec Java 1.5 et améliore la lisibilité du code lorsqu'elle est utilisée correctement. Cette construction se trouve le plus souvent dans les tests JUnit, car presque tous les développeurs de tests utilisent l'importation static pour les méthodes assert, par exempleassertEquals()
, et leurs variantes surchargées.Ce sera tout pour cette fois. Tout programmeur Java se doit de connaître tous les aspects du modificateur static mentionné ci-dessus. Cet article a passé en revue les informations de base sur les variables, champs, méthodes, blocs d'initialisation et importations static. Il a également évoqué certaines propriétés importantes qui sont essentielles à savoir pour écrire et comprendre les programmes Java. J'espère que chaque développeur perfectionnera son utilisation des membres static, car c'est un aspect très important pour le développement sérieux de logiciels. »
Cet article est également disponible en anglais: |
---|
Read the English version of this article to become an expert on Java’s static keyword. It points out some of the nuances of static Java classes and static Java methods. |
GO TO FULL VERSION