La différence entre les variables membres statiques et les variables membres non statiques
Prenons l'exemple suivant comme exemple
package cn.galc.test;public class Cat { /** * Variable membre statique*/ private static int sid = 0; private String name; } public void info() { System.out.println("Mon nom est " + nom + ",NO." + id } public static void main(String[] args) { Cat.sid); = 100; Chat mimi = new Cat("mimi"); Chat pipi = new Cat("pipi");Comprendre le processus d'exécution de l'ensemble du programme en dessinant des diagrammes d'analyse de la mémoire
Lors de l'exécution de la première phrase du programme : Cat.sid = 100 ;, le sid est ici une variable membre statique. La variable statique est stockée dans la zone de données (data seg), donc allouez d'abord un petit espace sid dans la zone de données. . Une fois la phrase exécutée, le sid contient une valeur de 100.
Le schéma d'agencement de la mémoire à l'heure actuelle est le suivant :
Ensuite, le programme exécute :
Chat mimi = nouveau Chat("mimi");Ici, la méthode constructeur Cat(String name) de la classe Cat est appelée. La méthode constructeur est définie comme suit :
Chat (nom de la chaîne){ this.name = nom; id=sid++ } Lors de l'appel, allouez d'abord un petit morceau de mémoire mm dans la mémoire de pile, qui contient l'adresse de l'objet instance de la classe Cat dans la mémoire tas. mm est l'objet de référence de l'objet de classe Cat dans la mémoire tas. Ce constructeur déclare une variable de paramètre formelle de type chaîne, donc "mimi" est transmis au constructeur en tant que paramètre réel. Puisque la constante de chaîne est allouée et stockée dans la zone de données, il y a un petit morceau de mémoire supplémentaire dans la zone de données. . Utilisé pour stocker la chaîne "mimi". La répartition de la mémoire à ce moment est illustrée dans la figure ci-dessous :
Lors de l'appel du constructeur, allouez d'abord un petit espace dans la mémoire de la pile pour le nom du paramètre formel, puis transmettez la chaîne "mimi" comme paramètre réel au nom. La chaîne est également un type de référence, sauf pour ces quatre et huit. types de données de base, tous les autres sont des types de référence, on peut donc considérer qu'une chaîne est également un objet. Cela équivaut donc à passer la référence de l'objet "mimi" à name, donc maintenant name pointe vers "mimi". La disposition de la mémoire à ce moment est donc la suivante :
Ensuite, exécutez le code dans le corps du constructeur :
this.name=nom;
Ceci fait ici référence à l'objet actuel, qui fait référence au chat dans la mémoire du tas. Ici, la valeur contenue dans le nom dans la pile est transmise à l'attribut name de l'objet cat dans la mémoire du tas, donc à ce moment la valeur contenue dans le nom peut également être trouvée dans l'objet chaîne "mimi" situé dans le Zone de données. A ce moment, ce nom est également un objet de référence de l'objet chaîne "mimi". Grâce à sa valeur d'attribut, l'objet chaîne "mimi" situé dans la zone de données peut être trouvé. La répartition de la mémoire à ce moment est illustrée dans la figure ci-dessous :
Ensuite, exécutez une autre ligne de code dans le corps de la méthode :
identifiant=sid++;
Ici, la valeur de sid est transmise à id, donc la valeur de id est 100. Une fois le sid transmis, ajoutez 1. À ce stade, sid devient 101. La disposition de la mémoire à ce moment est illustrée dans la figure ci-dessous.
A ce stade, la méthode constructeur est appelée, et tout l'espace mémoire occupé par les variables locales allouées à cette méthode constructeur disparaîtra, donc le nom mémoire situé dans l'espace pile disparaît. La référence à l'objet chaîne "mimi" dans la zone de données de la mémoire pile disparaît également. À ce stade, seule la référence à l'objet chaîne "mimi" dans la mémoire tas reste. La disposition de la mémoire à ce moment est la suivante :
Exécutez ensuite :
Chat pipi = new Cat("pipi"); Voici le deuxième appel à la méthode constructeur Cat(). L'ensemble du processus d'appel est le même que la première fois. Une fois l'appel terminé, la disposition de la mémoire à ce moment est celle indiquée dans la figure ci-dessous :
Les deux dernières lignes de code sont imprimées en appelant la méthode info(). Les résultats de l'impression sont les suivants :
Grâce à ce programme, nous pouvons voir le rôle de cette variable membre statique sid, qui peut être comptée. Chaque fois qu'un nouveau chat sort, donnez-lui un numéro. Laissez-le ajouter 1 par lui-même.
Une fois le programme exécuté, l'ensemble de la disposition dans la mémoire sera tel qu'indiqué dans la figure ci-dessus. Continue jusqu'au moment avant la fin de l'appel de la méthode principale.
Ici, la méthode constructeur Cat(String name) est appelée pour créer deux chats. Tout d'abord, deux petits espaces, mimi et pipi, sont alloués dans la mémoire de la pile, qui contiennent les adresses où se trouvent les deux chats. aux adresses dans la mémoire du tas. Deux citations de chat. La méthode de construction déclare ici une variable de type chaîne. La constante de chaîne est allouée dans la zone de données, donc les chaînes transmises mimi et pipi seront stockées dans la zone de données. Par conséquent, la zone de données se voit attribuer deux petits blocs de mémoire pour stocker les chaînes mimi et pipi, qui contiennent les chaînes « mimi » et « pipi ». Les chaînes sont également des types de référence en plus des quatre et huit types de données de base. Tous les types de données sont des types de référence. Vous pouvez donc considérer une chaîne comme un objet.
Voici deux nouveaux chats. Les deux chats ont leurs propres attributs id et name, donc l'id et le nom ici sont des variables membres non statiques, c'est-à-dire qu'il n'y a pas de modification statique. Ainsi, chaque fois qu'un nouveau chat est créé, ce nouveau chat a son propre identifiant et son propre nom, c'est-à-dire que les variables membres non statiques id et name ont des copies séparées pour chaque objet. Mais pour les variables membres statiques, il n'y a qu'une seule copie. Quel que soit le nombre d'objets nouveaux, même s'il n'y a pas de nouveaux objets, les variables membres statiques conserveront une copie dans la zone de données. Comme le sid ici, le sid est stocké dans la zone de données. Quel que soit le nombre de nouveaux chats dans la mémoire tas, il n'y a qu'une seule copie du sid, et une seule copie est conservée dans la zone de données.
Les variables membres statiques appartiennent à la classe entière, elles n'appartiennent pas à un objet spécifique. Alors, comment accéder à la valeur de cette variable membre statique ? Tout d'abord, n'importe quel objet peut accéder à cette valeur statique, et lors de l'accès, il accède à la même mémoire. Le deuxième point est que vous pouvez accéder à cette valeur statique même s'il n'y a pas d'objet. Vous pouvez accéder à cette valeur statique via "nom de classe.nom de variable membre statique", donc à l'avenir, vous verrez un certain nom de classe plus "." suivi de S'il y a une chose, alors la chose suivante doit être statique, comme "System.out". Ici, cette sortie est accessible via le nom de la classe (classe System) plus ".", donc cette sortie doit être statique.
Si un membre de la classe est déclaré statique, il est accessible avant la création d'un objet de la classe sans avoir à référencer un objet. L'exemple le plus courant de membre statique est main(). Étant donné que main() doit être appelé lorsque le programme commence son exécution, il est déclaré statique.
Les variables déclarées statiques sont essentiellement des variables globales. Lorsqu'un objet est déclaré, une copie de la variable statique n'est pas générée, mais toutes les variables d'instance de la classe partagent la même variable statique. Par exemple : déclarez un nombre de variables statiques comme le nombre de nouvelles instances de classe. Les méthodes déclarées statiques ont les restrictions suivantes :
(1). Ils ne peuvent appeler que d’autres méthodes statiques.
(2) Ils ne peuvent accéder qu’aux données statiques.
(3). Ils ne peuvent en aucun cas faire référence à ceci ou au super.
Si vous devez initialiser vos variables statiques par calcul, vous pouvez déclarer un bloc statique. Le bloc statique n'est exécuté qu'une seule fois lors du chargement de la classe. L'exemple ci-dessous montre
La classe a une méthode statique, quelques variables statiques et un bloc d'initialisation statique : public class UserStatic { static int a = 3; static void meth(int x) { System.out.println("x = " + x); System.out.println("a = " + a); System.out.println("b = " + b); static { System.out.println("Bloc statique initialisé."); b = a * 4; } public static void main(String args[]) { meth(42); } } Une fois la classe UseStatic chargée, toutes les instructions statiques sont exécutées. Tout d'abord, a est défini sur 3, puis le bloc statique est exécuté (impression d'un message) et enfin, b est initialisé à a*4 ou 12. Ensuite, main() est appelé, main() appelle meth(), en passant la valeur 42 à x. Les trois instructions println() font référence à deux variables statiques a et b et à la variable locale x.
Remarque : Il est illégal de référencer des variables d'instance dans une méthode statique.
Voici le résultat de ce programme :
Bloc statique initialisé x = 42 a = 3 b = 12.
Les méthodes et variables statiques peuvent être utilisées indépendamment de tout objet en dehors de la classe dans laquelle elles sont définies. Dans ce cas, il vous suffit d'ajouter l'opérateur point (.) après le nom de la classe. Par exemple, si vous souhaitez appeler une méthode statique depuis l'extérieur de la classe, vous pouvez utiliser le format général suivant :
nom de classe.method()
Ici, classname est le nom de la classe dans laquelle la méthode statique est définie. Comme vous pouvez le voir, ce format est similaire au format d'appel de méthodes non statiques via des variables de référence d'objet. Une variable statique est accessible dans le même format : le nom de la classe plus l'opérateur point. C'est ainsi que Java implémente une version contrôlée des fonctions globales et des variables globales.
Résumer:
(1) Les membres statiques ne sont pas accessibles par les instances créées par la classe dans laquelle ils se trouvent.
(2) Si les membres sans modification statique sont des membres objets, ils appartiennent à chaque objet.
(3) Les membres modifiés avec static sont des membres de classe, qui peuvent être directement appelés par une classe et sont communs à tous les objets.
Java Statique : En tant que modificateur, il peut être utilisé pour modifier des variables, des méthodes et des blocs de code (mais il ne doit pas modifier les classes).
(1) Modifier les variables :
Propriété partagée par tous les objets d'une classe, également appelée variable de classe. Ceci est similaire aux variables globales du langage C. Les variables de classe sont initialisées lorsque la classe est chargée et initialisées une seule fois. Lorsqu'un objet du programme modifie une variable statique, les autres objets verront la valeur modifiée. Les variables de classe peuvent donc être utilisées comme compteurs. De plus, les variables Java Static sont accessibles directement à l'aide du nom de classe sans nécessiter d'objet.
(2) Méthode de modification :
Une fonction commune à tous les objets d’une classe est appelée méthode statique. Les méthodes statiques sont également accessibles directement à l'aide du nom de la classe, sans nécessiter d'objet. Par conséquent, les variables non statiques et les méthodes non statiques ne sont pas directement accessibles dans les méthodes statiques, et les mots-clés tels que this ou super ne peuvent pas apparaître dans les méthodes statiques.
(3) Modifier les blocs de code Java :
Utilisez static pour modifier un bloc de code indépendant dans une classe, appelé bloc de code statique. Les blocs de code statiques sont exécutés lorsque la classe est chargée pour la première fois, et une seule fois. Les blocs de code statiques n'ont pas de nom, ils ne peuvent donc pas être appelés explicitement, mais ne sont appelés par la machine virtuelle que lorsque la classe est chargée. Il est principalement utilisé pour effectuer certaines opérations d'initialisation.
(4) Parlons du chargement des classes :
Lorsque la JVM utilise une classe pour la première fois, elle ira vers le chemin spécifié par le chemin de classe pour trouver le fichier de bytecode correspondant à la classe, le lira dans la JVM et l'enregistrera. Ce processus est appelé chargement de classe.
On peut voir que qu'il s'agisse d'une variable, d'une méthode ou d'un bloc de code, tant qu'elle est modifiée avec static, elle sera "prête" lorsque la classe sera chargée, c'est-à-dire qu'elle pourra être utilisée ou aura été exécutée. Tout peut être exécuté sans objets. Au contraire, s'il n'y a pas de statique, il faut y accéder via l'objet.