Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage
 <<    <     >    >>   API  Kapitel 9 - OOP II: Vererbung, Polymorphismus und statische Elemente

9.3 Statische Methoden und Membervariablen



9.3.1 Klassenvariablen

Java ist eine konsequent objektorientierte Sprache, in der es weder globale Funktionen noch globale Variablen gibt. Da es aber mitunter sinnvoll ist, Eigenschaften zu verwenden, die nicht an Instanzen einer Klasse gebunden sind, haben die Sprachdesigner das Attribut static für Methoden und Variablen eingeführt. Eine Variable, die innerhalb einer Klasse mit dem Attribut static versehen wurde, nennt man Klassenvariable (oder auch Statische Variable). Im Gegensatz zu Instanzvariablen, die immer an ein konkretes Objekt gebunden sind, existieren Klassenvariablen unabhängig von einem Objekt.

Jede Klassenvariable wird nur einmal angelegt und kann von allen Methoden der Klasse aufgerufen werden. Da sich alle Methoden die Variable »teilen«, sind Veränderungen, die eine Instanz vornimmt, auch in allen anderen Instanzen sichtbar. Klassenvariablen sind daher vergleichbar mit globalen Variablen, denn ihre Lebensdauer erstreckt sich auf das gesamte Programm. Namenskollisionen können allerdings nicht auftreten, denn der Zugriff von außen erfolgt durch Qualifizierung mit dem Klassennamen in der Form Klassenname.Variablenname.

Ein einfaches Beispiel für die Verwendung von Klassenvariablen besteht darin, einen Instanzenzähler in eine Klasse einzubauen. Hierzu wird eine beliebige Klassenvariable eingeführt, die beim Erzeugen eines Objekts hoch- und beim Zerstören heruntergezählt wird. Das folgende Beispiel demonstriert das für die Klasse Auto:

001 /* Testauto.java */
002 
003 public class Testauto
004 {
005   static private int objcnt = 0;
006 
007   public Testauto()
008   {
009     ++objcnt;
010   }
011 
012   public void finalize()
013   {
014     --objcnt;
015   }
016 
017   public static void main(String[] args)
018   {
019     Testauto auto1;
020     Testauto auto2 = new Testauto();
021     System.out.println(
022       "Anzahl Testauto-Objekte: " + Testauto.objcnt
023     );
024   }
025 }
Testauto.java
Listing 9.7: Realisierung eines Instanzenzählers mit Klassenvariablen

Die Ausgabe des Programms ist:

Anzahl Testauto-Objekte: 1

Mit auto2 wurde eine Instanz der Klasse erzeugt, auto1 ist dagegen zum Zeitpunkt der Ausgabeanweisung lediglich eine noch nicht initialisierte Objektreferenz.

9.3.2 Konstanten

Eine andere Anwendung von Klassenvariablen besteht in der Deklaration von Konstanten. Dazu wird das static-Attribut mit dem final-Attribut kombiniert, um eine unveränderliche Variable mit unbegrenzter Lebensdauer zu erzeugen:

001 public class Auto
002 {
003   private static final double STEUERSATZ = 18.9;
004 }
Listing 9.8: Verwendung von Klassenvariablen zur Definition von Konstanten

Durch die Anwendung von final wird verhindert, dass der Konstanten STEUERSATZ während der Ausführung des Programms ein anderer Wert zugewiesen wird. Da Java keinen Präprozessor enthält und damit keine #define-Anweisung kennt, ist die beschriebene Methode das einzige Verfahren zur Deklaration von Konstanten in Java. Die Konvention, Konstantennamen groß zu schreiben, wurde dabei von C übernommen.

9.3.3 Klassenmethoden

Neben Klassenvariablen gibt es in Java auch Klassenmethoden, d.h. Methoden, die unabhängig von einer bestimmten Instanz existieren. Sie werden auch als statische Methoden bezeichnet. Klassenmethoden werden ebenfalls mit Hilfe des static-Attributs deklariert und - analog zu Klassenvariablen - durch Voranstellen des Klassennamens aufgerufen.

Da Klassenmethoden unabhängig von konkreten Instanzen ihrer Klasse existieren, ist ein Zugriff auf Instanzvariablen nicht möglich. Diese Trennung äußert sich darin, dass Klassenmethoden keinen this-Zeiger besitzen. Der Zugriff auf Instanzvariablen und der Aufruf von Instanzmethoden wird daher schon zur Compile-Zeit als Fehler erkannt.

Klassenmethoden werden häufig da eingesetzt, wo Funktionalitäten zur Verfügung gestellt werden, die nicht datenzentriert arbeiten oder auf primitiven Datentypen operieren. Beispiele für beide Arten sind in der Klassenbibliothek zu finden. Zur ersten Gruppe gehören beispielsweise die Methoden der Klasse System. Die Klasse System ist eine Art Toolbox, die Funktionen wie Aufruf des Garbage Collectors oder Beenden des Programms zur Verfügung stellt. Zur zweiten Gruppe gehören beispielsweise die Methoden der Klasse Math, die eine große Anzahl an Funktionen zur Fließkomma-Arithmetik zur Verfügung stellen. Da die Fließkommatypen primitiv sind, hätte ein instanzbasiertes Methodendesign an dieser Stelle wenig Sinn.

Eine weitere Anwendung für Klassenmethoden liegt in der Instanzierung von Objekten der eigenen Klasse. Beispiele dafür finden sich in den Design-Patterns Singleton (siehe Abschnitt 11.4.1) und Factory-Methode (siehe Abschnitt 11.4.4).

 Tip 

Das folgende Listing zeigt die Verwendung der Klassenmethode sqrt der Klasse Math zur Ausgabe einer Tabelle von Quadratwurzeln:

001 /* Listing0909.java */
002 
003 public class Listing0909
004 {
005   public static void main(String[] args)
006   {
007     double x, y;
008     for (x = 0.0; x <= 10.0; x = x + 1.0) {
009       y = Math.sqrt(x);
010       System.out.println("sqrt("+x+") = "+y);
011     }
012   }
013 }
Listing0909.java
Listing 9.9: Verwendung von Math.sqrt

Die Ausgabe des Programms ist:

sqrt(0.0) = 0.0
sqrt(1.0) = 1.0
sqrt(2.0) = 1.4142135623730951
sqrt(3.0) = 1.7320508075688772
sqrt(4.0) = 2.0
sqrt(5.0) = 2.23606797749979
sqrt(6.0) = 2.449489742783178
sqrt(7.0) = 2.6457513110645907
sqrt(8.0) = 2.8284271247461903
sqrt(9.0) = 3.0
sqrt(10.0) = 3.1622776601683795

Die statische Methode main

Ein schon bekanntes Beispiel für eine Klassenmethode ist die Methode main, die als Startpunkt in Applikationen verwendet wird. Im Gegensatz zu Applets, bei denen vom Laufzeitsystem eine Instanz der Applet-Klasse erzeugt und dann durch Aufruf von Callback-Methoden bedient wird, erfolgt der Start einer Applikation ohne die Instanzierung einer Klasse. Der Java-Interpreter lädt lediglich das beim Starten angegebene Klassenobjekt und sucht nach einer statischen Methode mit der Signatur:

public static void main(String[] args)

Wird diese gefunden, stellt es ein Array mit den Kommandozeilenparametern zusammen und übergibt es als Argument an main. Wird keine Methode mit dieser Signatur gefunden, gibt es einen Laufzeitfehler.

9.3.4 Statische Initialisierer

Bisher haben wir nur die Möglichkeit kennengelernt, statischen Variablen während der Deklaration einen Wert zuzuweisen. Falls komplexere Initialisierungen benötigt werden, können zur Initialisierung von statischen Variablen statische Initialisierer definiert werden.

Sie ähneln gewöhnlichen Konstruktoren und dienen wie diese dazu, Variablen mit einem definierten Startwert zu belegen. Im Gegensatz zu einem gewöhnlichen Konstruktor erfolgt der Aufruf eines statischen Initialisierers aber nicht mit jedem neu angelegten Objekt, sondern nur einmal, wenn die Klasse geladen wird.

Ein statischer Initialisierer wird als parameterlose Methode mit dem Namen static definiert:

001 class Test
002 {
003   static int i;
004   static int j;
005 
006   static
007   {
008     i = 5;
009     j = 3 * i;
010   }
011 }
Listing 9.10: Definition eines statischen Initialisierers

Da der statische Initialisierer vom Laufzeitsystem aufgerufen wird, wenn die Klasse geladen wird, ist eine benutzerdefinierte Parametrisierung nicht möglich.

Es ist erlaubt, mehrere statische Initialisierer innerhalb einer Klasse zu definieren. Sie werden dann nacheinander in der textuellen Reihenfolge ihrer Deklaration ausgeführt. Wechseln sich initialisierte statische Variablen und statische Initialisierer im Quelltext ab, werden beide gleichwertig behandelt, d.h., die Ausführung erfolgt unabhängig vom Typ in textueller Reihenfolge. Eine Ausnahme bilden lediglich die statischen Variablen, denen Konstanten zugewiesen werden, deren Wert bereits zur Compile-Zeit feststeht. Ihre Initialisierung erfolgt - unabhängig von ihrer Position im Quellcode - unmittelbar nach dem Laden der Klasse.

 Hinweis 


 Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0
 <<    <     >    >>   API  © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de