CodeGym /Java-Blog /Germany /Static-Modifikator in Java
Autor
Pavlo Plynko
Java Developer at CodeGym

Static-Modifikator in Java

Veröffentlicht in der Gruppe Germany
Der static-Modifikator in Java zeigt an, das etwas direkt zu einer Klasse gehört: Ein statisches Feld gehört zu einer Klasse; eine statische Methode ebenso. Statische Methoden sind sehr wichtig. Doch was bedeutet static in Java? Du kannst den Klassennamen verwenden, um eine statische Methode aufzurufen oder ein statisches Feld zu referenzieren. Wenn zum Beispiel das Feld count in der Klasse Counter statisch ist, dann kannst du die Variable mit dem folgenden Ausdruck referenzieren: Counter.count. Natürlich müssen auch die Zugriffsmodifikatoren berücksichtigt werden. Zum Beispiel sind private-Felder nur innerhalb der Klasse verfügbar, in der sie deklariert wurden, während protected-Felder für alle Klassen innerhalb eines Pakets verfügbar sind, sowie für alle ihre Unterklassen außerhalb des Pakets. Angenommen, die Klasse Counter hat eine statische Methode increment(), deren Aufgabe es ist, das Feld count zu inkrementieren. Du kannst diese Methode mit Counter.increment() aufrufen. Man muss keine Instanz der Klasse Counter erstellen, um auf ein statisches Feld oder eine Methode zuzugreifen. Dies ist der grundlegende Unterschied zwischen statischen (Klassen-)Variablen und Methoden und NICHT-statischen (Instanz-)Variablen und Methoden. Ein wichtiger Hinweis. Vergiss nicht, dass die statischen Mitglieder der Klasse direkt zur Klasse gehören, nicht zu irgendeiner Instanz der Klasse. Das heißt, dass der Wert der count-Variable für alle Counter-Objekte gleich ist. In diesem Artikel sehen wir uns die Grundlagen der Verwendung des static-Modifikators in Java an, sowie einige Funktionen, die dir helfen werden, wichtige Programmierkonzepte zu verstehen. Static-Modifikator in Java - 1

Was jeder Programmierer über den static-Modifikator in Java and Java statische methoden wissen sollte.

In diesem Abschnitt schauen wir uns die wichtigsten Aspekte der Verwendung von statischen Methoden, statischen Feldern und statischen Klassen an. Beginnen wir mit Variablen.
  1. Du kannst innerhalb eines static-Kontexts, wie zum Beispiel einer statischen Methode oder eines Blocks, NICHT auf nicht-statische Mitglieder einer Klasse zugreifen. Das Kompilieren des folgenden Codes führt zu einem Fehler:

    
    public class Counter {
    private int count;
    public static void main(String args []) {
       System.out.println(count); //  Compile time error
    }
    }
    

    Dies ist einer der häufigsten Fehler von Java-Programmierern, besonders von Einsteigern. Da die main-Methode statisch ist und die count-Variable nicht, löst die Verwendung der println-Methode innerhalb der main-Methode einen Fehler zur Kompilierzeit aus.

  2. Im Gegensatz zu lokalen Variablen, sind statische Felder und Methoden in Java NICHT thread safe. In der Praxis ist dies eine der häufigsten Ursachen für Sicherheitsprobleme bei Multithread-Programmierung. Da jede Instanz einer Klasse auf die gleiche Kopie einer statischen Variable verweist, muss eine solche Variable von der Klasse geschützt oder „gesperrt“ werden. Wenn du also statische Variablen verwendest, stelle sicher, dass sie richtig synchronized werden, um Probleme wie sogenannte race conditions zu vermeiden.

  3. Statische Methoden haben den praktischen Vorteil, dass man nicht jedes Mal ein neues Objekt erstellen muss, wenn man sie aufrufen will. Eine statische Methode kann mit dem Namen der Klasse aufgerufen werden, die sie deklariert. Deshalb sind diese Methoden perfekt für factory- und utility-Methoden. Die Klasse java.lang.Math ist ein sehr schönes Beispiel: fast alle ihre Methoden sind statisch. Javas Utility-Klassen sind aus demselben Grund als final gekennzeichnet.

  4. Ein weiterer wichtiger Punkt ist, dass du (@Override) statische Methoden nicht überschreiben kannst. Wenn du eine identische Methode in einer subclass deklarierst, d.h. eine Methode mit demselben Namen und derselben Signatur, „versteckst“ du lediglich die Methode der superclass, anstatt sie zu überschreiben. Dieses Phänomen wird als method hiding bezeichnet. Das bedeutet, wenn sowohl in den Eltern- als auch in den Kindklassen eine statische Methode deklariert ist, wird die aufgerufene Methode immer auf dem Variablentyp zur Kompilierzeit basieren. Anders als beim Überschreiben von Methoden, werden solche Methoden nicht ausgeführt, wenn das Programm läuft. Sehen wir uns ein Beispiel an:

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

    Konsolenausgabe:

    Inside the parent class / static method

    Der Code zeigt deutlich, dass trotz der Tatsache, dass das Objekt ein Car ist, die statische Methode in der Klasse Vehicle aufgerufen wird, da die Methode zur Kompilierzeit aufgerufen wurde. Und beachte, dass es keine Kompilierfehler gab!

  5. Außerdem kannst du, abgesehen von den Klassen der obersten Ebene, statische Klassen innerhalb anderer Klassen deklarieren. Solche Klassen sind als nested static classes bekannt. Sie sind hilfreich für eine stärkere Integration. Ein markantes Beispiel für eine statische verschachtelte Klasse ist HashMap.Entry, die eine Datenstruktur in HashMap ist. Bemerkenswert ist, dass statische verschachtelte Klassen, wie innere Klassen, in einer separaten .class-Datei deklariert werden. Wenn du also fünf verschachtelte Klassen in deiner Hauptklasse deklarierst, wirst du 6 Dateien mit der Endung .class haben. Ein anderes Beispiel ist die Deklaration unseres eigenen Comparator, wie zum Beispiel ein Altersvergleich (AgeComparator) in der Klasse Employee.

  6. Der static-Modifikator kann auch in einem statischen Initialisierungsblock verwendet werden, besser bekannt als „statischer Block“, der ausgeführt wird, wenn die Klasse geladen wird. Wenn du einen solchen Block nicht deklarierst, sammelt Java alle statischen Felder in einer einzigen Liste und initialisiert sie, wenn die Klasse geladen wird. Ein statischer Block kann KEINE Checked Exceptions auslösen, aber er kann nicht überprüfte Ausnahmen auslösen. In diesem Fall tritt die Ausnahme ExceptionInInitializerError auf. In der Praxis wird jede Ausnahme, die während der Initialisierung von statischen Feldern auftritt, von Java in diesen Fehler gehüllt. Das ist auch die häufigste Ursache für den Fehler NoClassDefFoundError, weil die Klasse nicht im Speicher ist, wenn sie referenziert wird.

  7. Es ist gut zu wissen, dass statische Methoden zur Kompilierzeit verlinkt werden, im Gegensatz zur Verlinkung von virtuellen oder nicht-statischen Methoden, die zur Laufzeit verlinkt werden, wenn ein bestimmtes Objekt aufgerufen wird. Dementsprechend können in Java statische Methoden nicht überschrieben werden, da der Polymorphismus auf sie zur Laufzeit nicht anwendbar ist. Dies ist eine wichtige Einschränkung, die man beachten sollte, wenn man eine Methode als static deklariert. Das ist nur dann sinnvoll, wenn es keine Möglichkeit oder Notwendigkeit gibt, die Methode in einer Unterklasse zu überschreiben. Factory-Methoden und Utility-Methoden sind gute Beispiele für den richtigen Gebrauch des static-Modifikators. Joshua Bloch weist in seinem Buch Effective Java, das für jeden Java-Programmierer absolute Pflichtlektüre ist, auf einige Vorteile hin, die statische Factory-Methoden gegenüber Konstruktoren haben.

  8. Die Initialisierung ist ein wichtiger Aspekt eines statischen Blocks. Statische Felder oder Variablen werden initialisiert, nachdem die Klasse in den Speicher geladen wurde. Die Initialisierung erfolgt von oben nach unten, in derselben Reihenfolge, in der sie in der Quelldatei der Java-Klasse deklariert wurde. Da statische Felder Thread-sicher initialisiert werden, wird dieser Prozess auch zur Implementierung des Singleton-Musters verwendet. Wenn du aus irgendeinem Grund kein Enum als dein Singleton benutzt, dann hast du eine gute Alternative. Aber in diesem Fall musst du bedenken, dass dies keine „faule“ Initialisierung ist. Das bedeutet, dass das statische Feld initialisiert wird, noch BEVOR jemand danach „fragt“. Wenn ein Objekt ressourcenintensiv ist oder selten benutzt wird, dann wird die Initialisierung in einem statischen Block nicht zu deinem Vorteil funktionieren.

  9. Während der Serialisierung werden statische Felder, wie transient-Variablen, nicht serialisiert. Alle Daten, die in einem statischen Feld gespeichert werden, enthalten nach der Deserialisierung ihren Anfangswert (Standardwert). Wenn ein statisches Feld zum Beispiel ein int ist, wird sein Wert nach der Deserialisierung Null sein. Wenn sein Typ float ist, wird der Wert 0.0 sein. Wenn das Feld ein Object ist, wird der Wert null sein. Um ehrlich zu sein, ist dies eine der am häufigsten gestellten Fragen zur Serialisierung in Interviews für Java-Positionen. Speichere keine wesentlichen Objektdaten in einem statischen Feld!

  10. Zum Schluss sprechen wir noch über den statischen Import. Diese Verwendung des static-Modifikators ist eine Abwandlung der import-Standardanweisung. Der Unterschied besteht darin, dass du ein oder alle statischen Klassenmitglieder importieren kannst. Sobald statische Methoden importiert wurden, kann auf sie zugegriffen werden, als wären sie in der gleichen Klasse deklariert worden. Gleichermaßen können wir, indem wir statische Felder importieren, auf sie zugreifen, ohne den Klassennamen anzugeben. Diese Funktion wurde in Java 1.5 eingeführt und verbessert die Lesbarkeit des Codes, wenn sie richtig verwendet wird. Dieses Konstrukt findet man besonders häufig in JUnit-Tests, da fast alle Testentwickler den statischen Import für Assertmethoden verwenden, z.B. assertEquals() und ihre überladenen Varianten.

  11. Das wäre dann erstmal alles. Jeder Java-Programmierer muss alle oben genannten Aspekte des static-Modifikators kennen. In diesem Artikel haben wir uns die Grundlagen über statische Variablen, Felder, Methoden, Initialisierungsblöcke und Importe angesehen. Außerdem kamen einige wichtige Eigenschaften zur Sprache, die man kennen muss, um Java-Programme schreiben und verstehen zu können. Ich hoffe, dass jeder Entwickler seinen gekonnten Umgang mit statischen Mitgliedern perfektionieren wird, denn das ist sehr wichtig für eine ernstzunehmende Softwareentwicklung.“

Dieser Beitrag ist auf Englisch verfügbar.
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 methods in Java.
Kommentare (1)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Onur Bal Level 27, Istanbul, Turkey
4 Oktober 2020
Sehr guter Artikel!