Heim  >  Artikel  >  Web-Frontend  >  Das statische Schlüsselwort, das in den java_javascript-Kenntnissen erlernt werden muss

Das statische Schlüsselwort, das in den java_javascript-Kenntnissen erlernt werden muss

WBOY
WBOYOriginal
2016-05-16 15:27:512146Durchsuche

1. statisches Schlüsselwort

 

Es stellt sich heraus, dass für Mitgliedsvariablen in einer Klasse jedes neue Objekt seine eigene Mitgliedsvariable hat, da diese Mitgliedsvariablen keine statischen Mitgliedsvariablen sind. Für statische Mitgliedsvariablen gibt es nur eine Kopie dieser Mitgliedsvariablen, und diese Kopie wird von allen Objekten dieser Klasse gemeinsam genutzt.

1.1. Der Unterschied zwischen statischen Mitgliedsvariablen und nicht statischen Mitgliedsvariablen

Nehmen Sie das folgende Beispiel als Beispiel

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();
  }
}

Verstehen Sie den Ausführungsprozess des gesamten Programms, indem Sie ein Speicheranalysediagramm zeichnen

Beim Ausführen des ersten Satzes des Programms: Cat.sid = 100; ist die SID hier eine statische Mitgliedsvariable. Die statische Variable wird im Datenbereich (Datensegment) gespeichert. Weisen Sie daher zunächst einen kleinen Speicherplatz zu sid, nach der Ausführung des ersten Satzes gibt es einen Wert in sid, der 100 ist.

Das Speicherlayoutdiagramm sieht derzeit wie folgt aus

 

Der nächste Schritt besteht darin, das Programm auszuführen, um:

 Cat mimi = neue Katze („mimi“);

Hier wird der Konstruktor Cat(String name) der Cat-Klasse aufgerufen. Die Konstruktormethode ist wie folgt definiert:

 Katze (Stringname){

 this.name = name;

 id=sid ;

 }

Ordnen Sie beim Aufruf zunächst einen kleinen Speicherbereich mm im Stapelspeicher zu, der die Adresse des Instanzobjekts der Cat-Klasse im Heapspeicher enthält. mm ist das Referenzobjekt des Cat-Klassenobjekts im Heapspeicher . Dieser Konstruktor deklariert eine formale Parametervariable vom Typ String, daher wird „mimi“ als tatsächlicher Parameter an den Konstruktor übergeben. Da die String-Konstante im Datenbereich zugewiesen und gespeichert wird, ist im Datenbereich nur wenig Speicher vorhanden. Wird zum Speichern der Zeichenfolge „mimi“ verwendet. Die Speicherverteilung ist zu diesem Zeitpunkt wie folgt:

 

Wenn der Konstruktor aufgerufen wird, reservieren Sie zunächst einen kleinen Platz im Stapelspeicher für den Namen. Anschließend wird die Zeichenfolge „mimi“ als tatsächlicher Parameter übergeben .Typ, mit Ausnahme der vier und acht Basisdatentypen, alle anderen sind Referenztypen, sodass davon ausgegangen werden kann, dass eine Zeichenfolge auch ein Objekt ist. Dies entspricht also der Übergabe der Referenz des „mimi“-Objekts an name, sodass name nun auf „mimi“ verweist. Das Speicherlayout ist zu diesem Zeitpunkt also wie folgt:

Führen Sie als Nächstes den Code im Konstruktorkörper aus:

 this.name=name;

Dies bezieht sich hier auf das aktuelle Objekt, das sich auf die Katze im Heap-Speicher bezieht. Dabei wird der im Namen im Stack enthaltene Wert an das Namensattribut des Cat-Objekts im Heap-Speicher übergeben, sodass der im Namen enthaltene Wert auch im im Datenbereich befindlichen String-Objekt „mimi“ zu finden ist. Zu diesem Zeitpunkt ist dieser Name auch ein Referenzobjekt des String-Objekts „mimi“. Über seinen Attributwert kann das im Datenbereich befindliche String-Objekt „mimi“ gefunden werden. Die Speicherverteilung ist zu diesem Zeitpunkt wie folgt:

 

Führen Sie als Nächstes eine weitere Codezeile im Methodenkörper aus: id=sid; Hier wird der Wert von sid an id übergeben, sodass der Wert von id 100 beträgt. Nachdem sid übergeben wurde, addieren Sie selbst 1 und sid wird 101. Das Speicherlayout zu diesem Zeitpunkt ist in der folgenden Abbildung dargestellt.

 

Zu diesem Zeitpunkt wird die Konstruktormethode aufgerufen und der gesamte von den dieser Konstruktormethode zugewiesenen lokalen Variablen belegte Speicherplatz verschwindet, sodass der im Stapelbereich befindliche Namensspeicher verschwindet. Der Verweis auf das String-Objekt „mimi“ im Datenbereich im Stapelspeicher verschwindet ebenfalls. Zu diesem Zeitpunkt bleibt nur der Verweis auf das String-Objekt „mimi“ im Heap-Speicher übrig. Das Speicherlayout ist zu diesem Zeitpunkt wie unten dargestellt:

 

Nächste Ausführung:

Cat pipi = new Cat(“pipi”);

Hier ist der zweite Aufruf der Konstruktormethode Cat(). Der gesamte Aufrufvorgang ist der gleiche wie beim ersten Mal. Nach Abschluss des Aufrufs ist das Speicherlayout zu diesem Zeitpunkt wie folgt:

 

  最后两句代码是调用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();
  }
}

Der einzige Unterschied zwischen diesem Code und dem vorherigen Code besteht darin, dass der statische Modifikator der Sid-Variable entfernt wurde. Zu diesem Zeitpunkt ist Sid keine statische Mitgliedsvariable mehr, sondern eine nicht statische Mitgliedsvariable. Jedes von new erzeugte Katzenobjekt verfügt über ein eigenes separates Sid-Attribut. Nachdem dieser Code ausgeführt wurde, sieht das Layout im Speicher wie folgt aus:

 

Da sid zu einer nicht statischen Mitgliedsvariablen geworden ist, hat sie keine Zählfunktion mehr. Wie die Attribute id und name wird sid zu einem Attribut, das jedes neue Objekt hat, sodass jeder neuen Katze ein sid-Attribut hinzugefügt wird. Da auf die SID nicht mehr im Format „Klassenname. statischer Mitgliedsobjektname“ zugegriffen werden kann, kann der erste Satz des Codes „Cat.sid = 100;“ nicht auf diese Weise verwendet werden, da sonst ein Kompilierungsfehler auftritt. Dieser Satz muss auskommentiert werden, um erfolgreich zu sein. Da auf den Wert von sid nicht zugegriffen werden kann, ist der Wert von sid immer der bei der Initialisierung zugewiesene Wert 0. Bis der Konstruktor aufgerufen und der Code id=sid im Methodenkörper ausgeführt wird, weist sid zunächst id seinen eigenen Wert von 0 zu, sodass der Wert von id 0 ist, und dann addiert sid 1 zu sich selbst, sodass sid zu 1 wird.

Der Unterschied zwischen statischen und nicht statischen Variablen besteht also darin, dass statische Variablen zum Zählen verwendet werden können, nicht statische Variablen jedoch nicht.

Wenn Sie Gedächtnis verstehen, verstehen Sie alles und Sie verstehen verschiedene Sprachen. Alle Sprachen sind nichts anderes als Folgendes: Der für lokale Variablen zugewiesene Speicher befindet sich immer auf dem Stapel, der für neue Dinge zugewiesene Speicher befindet sich immer auf dem Heap und der für statische Dinge zugewiesene Speicher befindet sich immer im Datenbereich. Der Rest des Codes muss im Codebereich liegen. Alle Sprachen sind so.

Wenn Sie in einer statischen Methode auf eine nicht statische Mitgliedsvariable zugreifen möchten, können Sie nicht direkt darauf zugreifen. Sie müssen ein neues Objekt in der statischen Methode erstellen, um darauf zuzugreifen. Wenn eine statische Mitgliedsvariable hinzugefügt wird, ist diese Mitgliedsvariable eine statische Mitgliedsvariable und kann direkt in der Hauptmethode aufgerufen werden.

Die Hauptmethode ist eine statische Methode. Wenn die Hauptmethode ausgeführt werden soll, muss kein neues Objekt erstellt werden.

Dynamische Methoden werden für ein bestimmtes Objekt aufgerufen, während statische Methoden nicht für ein bestimmtes Objekt aufgerufen werden. Sie können weiterhin ohne Objekt verwendet werden. Sie können also die Form „classname.method()“ verwenden, um statische Methoden aufzurufen. Daher ist es nicht möglich, in der Hauptmethode auf nicht statische Mitgliedsvariablen zuzugreifen. Es ist auch nicht möglich, auf nicht statische Methoden in der Hauptmethode zuzugreifen, da nicht statische Methoden nur für ein bestimmtes Objekt aufgerufen werden können Kein Objekt, es kann nicht gefunden werden. Jetzt kommt der Ausführer der Methode.

Mitgliedsvariablen wird nur dann Speicherplatz im Heap-Speicher zugewiesen, wenn ein Objekt von new erstellt wird. Lokale Variablen weisen Speicherplatz im Stapelspeicher zu.

Statische Methoden werden für ein bestimmtes Objekt nicht mehr aufgerufen, daher kann nicht auf nicht statische Mitglieder zugegriffen werden.

Nicht statische Mitglieder sind exklusiv für ein bestimmtes Objekt. Wenn Sie auf nicht statische Mitglieder zugreifen möchten, müssen Sie ein neues Objekt erstellen, um darauf zuzugreifen.

Auf statische Variablen kann über Objektnamen oder Klassennamen zugegriffen werden. Beide greifen auf denselben Speicher zu.

Das Obige ist der gesamte Inhalt dieses Artikels. Es gibt viele Informationen und Sie müssen sie geduldig lesen, um das Java-Static-Schlüsselwort wirklich zu lernen.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn