Was bedeutet der Modifikator static?

Der Modifikator static kann, je nach Position, zu verschiedenen Zwecken verwendet werden, wird jedoch oft zur Speicheroptimierung eingesetzt.
Bei unreflektiertem Gebrauch kann es jedoch problematisch werden, wenn die Objektorientierung unterwandert wird. Die Verwendung des Schlüsselwortes sollte somit wohl überlegt sein und nur dort wahrgenommen werden, wo die Programmstruktur dies nahelegt.

static bei Variablen

Das Schlüsselwort kann Felder kennzeichnen, die dann als Klassenvariablen bezeichnet werden. Sie sind nicht den von der Klasse abgeleiteten Objekten zugeordnet, sondern gehören zur Klasse selbst und stehen in allen Instanzen gleichermaßen zur Verfügung. Außerhalb der deklarierenden Klasse werden sie mit dem vorangestellten und durch Punktoperator getrennten Klassennamen aufgerufen.
In Java werden Klassenvariablen häufig in Kombination mit dem Modifikator final für unveränderliche Werte an Stelle von Konstanten eingesetzt. Ihre Bezeichner werden dann durchgängig groß geschrieben.

public final class Math {
    //...
    public static final double PI = 3.14159265358979323846;
    //...
}
    
public class Font implements java.io.Serializable {
    //...
    public static final int ITALIC = 2;
    //...
}

Im Gegensatz zu nicht-statischen Feldern kann auf sie auch aus anderen statischen Umgebungen heraus (z.B. main()) direkt zugegriffen werden.

public class StaticBsp {
    static String testStr = "static Test";
    public static void main(String[] args) {
        System.out.println(Math.PI);
        System.out.println(testStr);
    }
}

static bei Methoden

Ähnlich den Klassenvariablen kann auch auf static deklarierte Methoden (Klassenmethoden) ohne Objektbildung zugegriffen werden. Aus anderen statischen Umgebungen heraus können sie direkt mit dem vorangestellten Klassennamen aufgerufen werden. Umgekehrt müssen alle Methoden selbst static sein, die innerhalb einer static deklarierten Umgebung direkt aufgerufen werden sollen.

public class StaticBsp {
    static String testStr = "static Test";
    public static void main(String[] args) {
        print();
    }
	
    static void print() {
        testStr = "changed " + testStr;
        System.out.println(testStr);  // changed static Test
    }
}

Statische Methoden können darüber hinaus auf statische Felder zugreifen und deren Werte ändern, natürlich nur, sofern diese nicht zusätzlich final deklariert sind.

static bei Statements

Innerhalb einer Klasse kann ein alleinstehender static deklarierter Block vorhanden sein. Er kann verwendet werden, um Klassenvariablen zu initialisieren und wird noch vor Aufruf von main() ausgewertet. Gelegentlich werden solche dynamisch gebundene Bibliotheken auf diese Weise geladen, die in main() bereits bereitstehen müssen.

import java.util.Scanner;

public class StaticBsp {
    static String testStr;
    static {
        System.out.println("Static block aufgerufen");
        testStr = new Scanner(System.in).next();
    }

    public static void main(String[] args) {
        System.out.println("main() aufgerufen");
        print();
    }
	
    static void print() {
        testStr = "changed " + testStr;
        System.out.println(testStr);
    }
}

Im Beispiel wird eine statische Variable testStr deklariert, jedoch nicht initialisiert. In einem statischen Block wird mit Hilfe der Klasse Scanner eine Eingabe von der Kommandozeile gelesen und damit die Klassenvariable initialisiert. Erst danach wird main() aufgerufen. Dort wiederum findet der Aufruf von print() statt, wo der Wert der Variablen noch einmal modifiziert und dann ausgegeben wird.