Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 

7.5 Klassen mit static-Elementen



Java ist eine konsequent objektorientierte Sprache, in der es weder globale Funktionen noch globale Variablen gibt. Da es aber mitunter sinnvoll ist, Methoden aufzurufen, die nicht an Instanzen einer Klasse gebunden sind, haben die Sprachdesigner das Attribut static für Methoden und Variablen eingeführt.

7.5.1 Klassenvariablen

Variablen, die innerhalb einer Klasse mit dem Attribut static versehen werden, nennt man Klassenvariablen. Im Gegensatz zu den Instanzvariablen, die an ein 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 gutes 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 7.22: Realisierung eines Instanzenzählers mit Klassenvariablen

 Beispiel 

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.

7.5.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 STEUERSATZ = 18.9;
004 }
Listing 7.23: Verwendung von Klassenvariablen zur Definition von Konstanten

Durch die Anwendung von final wird verhindert, daß der Konstanten STEUERSATZ während der Ausführung des Programms ein anderer Wert zugewiesen wird. Da Java keinen Präprozesor 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.

 Hinweis 

7.5.3 Klassenmethoden

Neben Klassenvariablen gibt es in Java auch Klassenmethoden, d.h. Methoden, die unabhängig von einer bestimmten Instanz existieren. 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, daß 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 stellt. Da die Fließkommatypen primitiv sind, hätte ein instanzbasiertes Methodendesign an dieser Stelle wenig Sinn gemacht.

 Tip 

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

001 /* Listing0724.java */
002 
003 public class Listing0724
004 {
005    public static void main(String[] args)
006    {
007       double x, y;
008 
009       for (x = 0.0; x <= 10.0; x = x + 1.0) {
010          y = Math.sqrt(x);
011          System.out.println("sqrt("+x+") = "+y);
012       }
013    }
014 }
Listing0724.java
Listing 7.24: 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
 Beispiel 

7.5.4 Statische Konstruktoren

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 Konstruktoren 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 Konstruktors aber nicht mit jedem neu angelegten Objekt, sondern nur einmal zu Beginn des Programms.

Ein statischer Konstruktor 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 7.25: Definition eines statischen Konstruktors

Da er vom Laufzeitsystem aufgerufen wird, wenn die Klasse geladen wird, ist eine benutzerdefinierte Parametrisierung nicht möglich. Eine Klasse darf mehr als einen statischen Konstruktor definieren, sie werden in der Reihenfolge ihrer Deklaration aufgerufen.


 Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 
Go To Java 2, Addison Wesley, Version 1.0.2, © 1999 Guido Krüger, http://www.gkrueger.com