Maison  >  Article  >  interface Web  >  Le mot clé statique qui doit être appris dans les compétences java_javascript

Le mot clé statique qui doit être appris dans les compétences java_javascript

WBOY
WBOYoriginal
2016-05-16 15:27:512146parcourir

1. mot-clé statique

 

Il s'avère que pour les variables membres d'une classe, chaque nouvel objet a sa propre variable membre, car ces variables membres ne sont pas des variables membres statiques. Pour les variables membres statiques, il n'existe qu'une seule copie de cette variable membre, et cette copie est partagée par tous les objets de cette classe.

1.1. 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 {

  /**
   * 静态成员变量
   */
  private static int sid = 0;

  private String name;

  int id;

  Cat(String name) {
    this.name = name;
    id = sid++;
  }

  public void info() {
    System.out.println("My Name is " + name + ",NO." + id);
  }

  public static void main(String[] args) {
    Cat.sid = 100;
    Cat mimi = new Cat("mimi");
    Cat pipi = new Cat("pipi");
    mimi.info();
    pipi.info();
  }
}

Comprendre le processus d'exécution de l'ensemble du programme en dessinant un diagramme 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 dans la zone de données. zone de données. sid, une fois la première phrase exécutée, il y a une valeur dans sid, qui est 100.

Le schéma de disposition de la mémoire à l'heure actuelle est le suivant

 

L'étape suivante consiste à exécuter le programme pour :

 Chat mimi = nouveau Chat("mimi");

Ici, le constructeur Cat(String name) de la classe Cat est appelé. 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 du tas. mm est l'objet de référence de l'objet de la classe Cat dans la mémoire du 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 une petite quantité de mémoire dans la zone de données. Utilisé pour stocker la chaîne "mimi". La répartition de la mémoire à ce moment est la suivante :

 

Lorsque le constructeur est appelé, allouez d'abord un petit espace dans la mémoire de la pile pour le nom du paramètre formel. Le nom est ensuite nommé. Ensuite, la chaîne "mimi" est transmise à name en tant que paramètre réel. . Type, à l'exception des 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 :

Exécutez ensuite le code dans le corps du constructeur :

 this.name=name;

Ceci fait référence ici à 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 tas, donc la valeur contenue dans le nom peut également être trouvée dans l'objet chaîne "mimi" situé dans la zone de données. A cette époque, 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 la suivante :

 

Ensuite, exécutez une autre ligne de code dans le corps de la méthode : id=sid;

Ici, la valeur de sid est transmise à id, donc la valeur de id est 100. Une fois le sid transmis, ajoutez 1 vous-même et 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 :

 

Prochaine exécution : Cat 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 la suivante :

 

  最后两句代码是调用info()方法打印出来,打印结果如下:

  

  通过这个程序,看出来了这个静态成员变量sid的作用,它可以计数。每当有一只猫new出来的时候,就给它记一个数。让它自己往上加1。

  程序执行完后,内存中的整个布局就如上图所示了。一直持续到main方法调用完成的前一刻。

  这里调用构造方法Cat(String name) 创建出两只猫,首先在栈内存里面分配两小块空间mimi和pipi,里面分别装着可以找到这两只猫的地址,mimi和pipi对应着堆内存里面的两只猫的引用。这里的构造方法声明有字符串类型的变量,字符串常量是分配在数据区里面的,所以这里会把传过来的字符串mimi和pipi都存储到数据区里面。所以数据区里面分配有存储字符串mimi和pipi的两小块内存,里面装着字符串“mimi”和“pipi”,字符串也是引用类型,除了那四类8种的基础数据类型之外,其他所有的数据类型都是引用类型。所以可以认为字符串也是一个对象。

  这里是new了两只猫出来,这两只猫都有自己的id和name属性,所以这里的id和name都是非静态成员变量,即没有static修饰。所以每new出一只新猫,这只新猫都有属于它自己的id和name,即非静态成员变量id和name是每一个对象都有单独的一份。但对于静态成员变量来说,只有一份,不管new了多少个对象,哪怕不new对象,静态成员变量在数据区也会保留一份。如这里的sid一样,sid存放在数据区,无论new出来了多少只猫在堆内存里面,sid都只有一份,只在数据区保留一份。

  静态成员变量是属于整个类的,它不属于专门的某个对象。那么如何访问这个静态成员变量的值呢?首先第一点,任何一个对象都可以访问这个静态的值,访问的时候访问的都是同一块内存。第二点,即便是没有对象也可以访问这个静态的值,通过“类名.静态成员变量名”来访问这个静态的值,所以以后看到某一个类名加上“.”再加上后面有一个东西,那么后面这个东西一定是静态的,如”System.out”,这里就是通过类名(System类)再加上“.”来访问这个out的,所以这个out一定是静态的。

再看下面的这段代码

package cn.galc.test;

public class Cat {

  /**
   * 这里面的sid不再是静态成员变量了,因为没有static修饰符,
   * 此时它就是类里面一个普通的非静态成员变量,和id,name一样,
   * 成为每一个new出来的对象都具有的属性。
   */
  private int sid = 0;

  private String name;

  int id;

  Cat(String name) {
    this.name = name;
    id = sid++;
  }

  public void info() {
    System.out.println("My Name is " + name + ",NO." + id);
  }

  public static void main(String[] args) {
    //Cat.sid = 100;这里不能再使用“类.静态成员变量”的格式来访问sid了,因为sid现在变成了非静态的成员变量了。所以必须要把这句话注释掉,否则无法编译通过。
    Cat mimi = new Cat("mimi");
    Cat pipi = new Cat("pipi");
    mimi.info();
    pipi.info();
  }
}

La seule différence entre ce code et le code précédent est que le modificateur statique de la variable sid est supprimé. À ce stade, sid n'est plus une variable membre statique, mais une variable membre non statique. chacun Les objets cat produits par new auront leurs propres attributs sid distincts. Ainsi, une fois ce code exécuté, la disposition dans la mémoire est la suivante :

 

Depuis que sid est devenue une variable membre non statique, elle n'a plus la fonction de comptage. Comme les attributs id et name, sid devient un attribut que possède chaque nouvel objet, donc chaque nouveau chat se voit ajouter un attribut sid. Puisque le sid n'est plus accessible au format "nom de classe. nom d'objet membre statique", la première phrase du code "Cat.sid =100;" ne peut pas être utilisée de cette manière, sinon une erreur de compilation se produira. Cette phrase doit être commentée pour réussir la compilation. Étant donné que la valeur de sid n'est pas accessible, la valeur de sid est toujours la valeur 0 attribuée lors de l'initialisation. Jusqu'à ce que le constructeur soit appelé et que le code id=sid dans le corps de la méthode soit exécuté, sid attribue d'abord sa propre valeur de 0 à id, donc la valeur de id est 0, puis sid s'ajoute 1, donc sid devient 1.

Ainsi, la différence entre les variables statiques et les variables non statiques est que les variables statiques peuvent être utilisées pour le comptage, mais pas les variables non statiques.

Si vous comprenez la mémoire, vous comprenez tout et vous comprenez différentes langues. Tous les langages ne sont rien de plus : la mémoire allouée aux variables locales est toujours sur la pile, la mémoire allouée aux nouveaux éléments est toujours sur le tas et la mémoire allouée aux éléments statiques est toujours dans la zone de données. Le reste du code doit être dans la zone de code. Toutes les langues sont comme ça.

Dans une méthode statique, si vous souhaitez accéder à une variable membre non statique, vous ne pouvez pas y accéder directement. Vous devez créer un nouvel objet dans la méthode statique pour y accéder. Si une variable membre statique est ajoutée, alors cette variable membre est une variable membre statique et est accessible directement dans la méthode principale.

La méthode main est une méthode statique. Lorsque la méthode main doit être exécutée, il n'est pas nécessaire de créer un nouvel objet.

Les méthodes dynamiques sont appelées pour un certain objet, tandis que les méthodes statiques ne sont pas appelées pour un certain objet. Elles peuvent toujours être utilisées sans objet. Vous pouvez donc utiliser la forme "classname.method()" pour appeler des méthodes statiques. Par conséquent, il n'est pas possible d'accéder aux variables membres non statiques dans la méthode principale, car les méthodes non statiques ne peuvent être appelées que pour un certain objet. aucun objet, il est introuvable. Vient maintenant l'exécuteur de la méthode.

Les variables membres ne se voient attribuer un espace de stockage dans la mémoire tas que lorsqu'un objet est créé par new. Les variables locales allouent de l'espace de stockage dans la mémoire de la pile.

Les méthodes statiques ne sont plus appelées sur un certain objet, les membres non statiques ne sont donc pas accessibles.

Les membres non statiques sont exclusifs à un certain objet. Si vous souhaitez accéder aux membres non statiques, vous devez créer un nouvel objet pour y accéder.

Les variables statiques sont accessibles via les noms d'objets ou les noms de classes. Les deux accèdent à la même mémoire.

Ce qui précède représente l'intégralité du contenu de cet article. Il y a beaucoup d'informations et vous devez les lire patiemment pour vraiment apprendre le mot-clé java static.

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn