Statische benannte Variablen in Java
Eine statische benannte Variable wird ganz ähnlich wie eine statische Konstante deklariert, nur daß das Schlüsselwort "final" entfällt.
Main.javaclass K { static int f = 56; }
public class Main
{ public static void main( String[] args )
{ System.out.println( K.f ); }}System.out56
Der Quelltext "static int" besteht aus dem Feldmodifizierer "static" und dem Typ "int". Der Feldmodifizierer "static" legt fest, daß die Variable statisch ist, also während der gesamten Laufzeit eines Programms existiert. Eine statische Variable wird inkarniert (d.h. ihre Laufzeit-Existenz beginnt), wenn seine Klasse initialisiert wird.
In der obenstehenden Quelldatei wurde aus der Methode "main" der Klasse "Main" auf ein statisches Feld der Klasse "K" zugegriffen. Die folgende Quelldatei zeigt, daß beim Zugriff auf ein Feld derselben Klasse "Main" keine Eingrenzung des Feldnamens durch einen vorangestellten Klassennamen notwendig ist.
Main.javapublic class Main
{ static int f = 43;
public static void main( String[] args )
{ System.out.println( f ); }}System.out43
Initialisierer
Die Syntax einer Variablendeklaration sieht auch die Möglichkeit einer Initialisierung vor, die den Anfangswert einer Variablen bestimmt. Ein angegebener Initialisierer 〈VariableInitializer 〉 ist ein Ausdruck, der bei der Initialisierung der Klasse ausgewertet wird. Dann wird der sich ergebende Wert in die Variable geschrieben. Dies passiert genau einmal während der Initialisierung der Klasse.
Eine Klasse wird höchstens einmal initialisiert. Falls die Klasse nicht schon initialisiert ist, so erfolgt die Initialisierung der Klasse unmittelbar bevor erstmals eine statische Methode der Klasse aufgerufen wird, erstmals eine Zuweisung an ein statisches Feld erfolgt, oder ein statisches Feld verwendet wird (falls der Bezug auf das Feld eine Übersetzungszeitkonstante ist) oder unter bestimmten anderen Umständen, die in dieser Lektion noch nicht behandelt werden sollen.
Die Initialisierer des statischen Klassenvariablen werden in der Reihenfolge ausgewertet, in der sie im Programmtext vorkommen. Daher sind vorwärtsgerichtete Bezugnahmen auf im Programmtext später definierte Klassenvariablen nicht erlaubt, obwohl sie im aktuellen Gültigkeitsbereich liegen. In der Klassendeklaration ""class C { static int i = j; static int j = 1; }" ist beispielsweise das erste Auftreten des Bezeichners "j" im Quelltext solch ein fehlerhafter Vorwärtsbezug.
Die Initialisierer müssen keine Laufzeitkonstanten sein, beliebige Ausdrücke sind erlaubt.
Statische Konstante, die mit Ausdrücken initialisiert werden, die bereits zur Übersetzungszeit feststehen, werden zuerst initialisiert und können dann als Übersetzungszeitkonstanten aufgefaßt werden.
Lesen
Das „Lesen“ aus einer statischen Variablen geschieht also durch Verwendung ihres (nötigenfalls eingegrenzten) Namens an einer Stelle, an der ein Wert erwartet wird. Der Name stellt dann also einen Ausdruck dar, dessen Wert durch den Wert der Variablen gegeben ist.
Vorgabewerte
Alle statischen Variablen werden zunächst mit einem Vorgabewert initialisiert, der dann gegebenenfalls durch den Wert eines möglicherweise angegebenen Initialisierers überschrieben wird.
Dieser Vorgabewert ist der Wert "0" oder der Wert "0." für Variablen vom Typ "int" bzw. vom Typ "double" und der Wert "false" für eine Variable vom Typ "boolean".
Main.javaclass K { static int i;
static double d; static boolean b; }
public class Main
{ public static void main( String[] args )
{ System.out.println( K.i );
System.out.println( K.d );
System.out.println( K.b ); }}System.out0
0.0
false
Hinsichtlich der Vorgabewerte verhält sich eine Konstante jedoch anders als eine Variable: Für eine statische Konstante gibt es nämlich keinen Vorgabewert, sie muß explizit initialisiert werden.
Main.javaclass K { static final int i; }
public class Main
{ public static void main( String[] args )
{ System.out.println( K.i ); }}Konsolejavac Main.java
Main.java:1: variable i might not have been initialized
class K { static final int i; }
Vorgabe-Zugriffsstatus
Felder haben einen bestimmten Zugriffsstatus, der bestimmt, von welchen Teilen des Quellcodes ein Zugriff möglich ist.
Wenn in der Deklaration eines Feldes nichts anderes angegeben ist, dann gilt die Vorgabe für den Zugriffsstatus: Der Zugriff ist nur aus demselben Paket heraus möglich, in dem auch das Feld deklariert ist. In der Klassendeklaration "public class DefaultField { static int v; }" hat das Feld "v" diesen Vorgabe-Zugriffsschutz, ist also nur aus dem Paket heraus zugänglich, zu dem die Klassendeklaration gehört.
Zugriffsstatus "public"
Bei einer Felddeklaration kann ausdrücklich der Feldmodifizierer "public" angegeben werden, dann ist der Zugriffsstatus "public". Man sagt auch, das Feld sei öffentlich sichtbar, habe öffentliche Sichtbarkeit oder sei öffentlich. In der Klassendeklaration "public class PublicField { public static int v; }" ist das Feld "v" öffentlich.
Auf ein öffentliches Feld sind Zugriffe aus allen Paketen und Klassen erlaubt.
Zugriffsstatus "private"
Wenn ein Feld mit dem Feldmodifizierer "private" deklariert wird, dann ist das Feld privat (hat private Sichtbarkeit oder ist privat sichtbar ). In der Klassendeklaration "public class PrivateField { private static int v; }" ist das Feld "v" privat.
Der Zugriff auf ein solches privates Feld ist nur aus Methoden heraus möglich, die direkt in derselben Klasse deklariert sind, wie das private Feld. Das Feld wird damit also zu einer „inneren Angelegenheit“ seiner Klasse, auf die kein Zugriff von anderen Klassen aus möglich ist. Man sagt auch das Feld sei (für andere Klassen) versteckt.
Solche privaten Felder spielen eine ganz besondere Rolle: Da ein Feld keine „Intelligenz“ hat, kann es bei Schreibzugriffen keine eventuell nötigen Prüfungen oder Maßnahmen einleiten. Oft ist solch eine „Intelligenz“ aber wünschenswert. Sie kann durch Methoden bereitgestellt werden, die aufgerufen werden, um ein Daten einer Klasse zu lesen oder zu schreiben. Damit diese Methoden ihre Dienste zuverlässig bereitstellen können, muß es aber verhindert werden, daß unter Umgebung dieser Methoden direkt auf ein Feld zugegriffen wird. Das kann dadurch geschehen, daß Felder als privat deklariert werden. Besonders im Rahmen der objektorientierten Programmierung wird Wert auf dieses Vorgehen gelegt, das auch als Kapselung oder Informationsversteck bezeichnet wird. Dieses Vorgehen wird empfohlen:
Wenn keine schwerwiegenden Gründe dagegen sprechen, sollten nicht-konstante Felder nie mit dem Zugriffsstatus "public" und möglichst mit dem Zugriffsstatus "private" deklariert werden.
Mehrere Felder
In einer Klasse können auch mehrere Felder zusammengefaßt werden.
Dies sollte eingesetzt werden, um solche Informationen zu bündeln, die gemeinsam eine bestimmte Sache repräsentieren. Es soll ein hohe Kohäsion angestrebt werden, das heißt eine hohe Zusammengehörigkeit der Bestandteile einer Klasse, so daß diese insgesamt wieder als eine Einheit aufgefaßt werden können.
So könnte eine Klasse beispielsweise einen Bildschirm darstellen, dessen Helligkeit und Kontrast veränderlich ist. Die Klasse kann dann ein Feld für die aktuelle Helligkeitseinstellung und gleichzeitig ein weiteres Feld für die aktuelle Kontrasteinstellung enthalten.
Screen.javapublic class Screen
{ private static double brightness;
private static double contrast;
/* weitere Felder und Methoden */ }
Übungsfrage
- Variablen
Main.java
public class Main
{ static int v = 2;
public static void main( String[] args )
{ System.out.println( v + 1 ); /**/ }}- Welchen Wert hat die Variable "v" am Ende der Methode "main" an der mit dem Text "/**/" gekennzeichneten Stelle?