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

9.2 Modifier



In diesem Kapitel wurden an verschiedenen Stellen Beispiele gezeigt, in denen Schlüsselwörter wie public oder private zusammen mit bestimmten Programmelementen verwendet wurden. Mit Hilfe dieser Attribute können die Eigenschaften von Klassen, Methoden und Variablen verändert werden. Sie haben insbesondere Einfluss auf die Lebensdauer, Sichtbarkeit und Veränderbarkeit dieser Programmelemente und werden meist als Modifier bezeichnet. Wir wollen sie nun im Zusammenhang betrachten und ihre Wirkungsweise auf die verschiedenen Elemente eines Java-Programms erläutern.

9.2.1 Sichtbarkeit

Die eingangs erwähnte Tatsache, dass in einer abgeleiteten Klasse alle Eigenschaften der Basisklasse übernommen werden, ist nicht in allen Fällen ganz korrekt. Zwar besitzt sie immer alle Variablen und Methoden der Basisklasse, kann aber unter Umständen nicht darauf zugreifen, wenn ihre Sichtbarkeit eingeschränkt wurde.

Die Sichtbarkeit von Variablen und Methoden wird mit Hilfe folgender Modifier geregelt:

Mit Hilfe dieser Sichtbarkeitsebenen kann der Zugriff auf Klassenelemente eingeschränkt werden. private-Elemente sollten immer dann verwendet werden, wenn implementierungsabhängige Details zu verstecken sind, die auch in abgeleiteten Klassen nicht sichtbar sein sollen. protected-Elemente sind vor Zugriffen von außen geschützt, können aber von abgeleiteten Klassen verwendet werden. Die public-Elemente schließlich bilden die für alle sichtbaren Teile einer Klassendefinition und können daher als ihre Schnittstelle angesehen werden. Nachfolgend werden die verschiedenen Sichtbarkeitsattribute noch einmal genau beschrieben. Elemente mit Standard-Sichtbarkeit verhalten sich innerhalb des Pakets wie public- und außerhalb wie private-Elemente.

9.2.2 Die Attribute im Überblick

Nachfolgend wollen wir die wichtigsten Attribute noch einmal zusammenfassend darstellen und ihre jeweiligen Auswirkungen auf die Sichtbarkeit, Lebensdauer oder Veränderbarkeit von Variablen, Methoden und Klassen beschreiben.

private

Methoden oder Variablen vom Typ private sind nur in der aktuellen Klasse sichtbar, in allen anderen Klassen bleiben sie dagegen unsichtbar.

Diese Einschränkung bedeutet überraschenderweise nicht, dass die Methoden einer Klasse nur auf die privaten Membervariablen des eigenen Objekts zugreifen dürfen. Vielmehr ist es ebenfalls möglich, (quasi von außen) auf die private-Variablen eines anderen Objekts zuzugreifen. Vorausgesetzt, es handelt sich um eine Instanz derselben Klasse.

Das folgende Beispielprogramm demonstriert dies mit Hilfe der Klasse ClassWithPrivateA, die eine private Membervariable a besitzt. An der Implementierung von setOtherA können wir erkennen, wie der Zugriff auf fremde Objekte desselben Typs möglich ist:

001 /* Listing0906.java */
002 
003 public class Listing0906
004 {
005   public static void main(String[] args)
006   {
007     ClassWithPrivateA a1 = new ClassWithPrivateA(7);
008     ClassWithPrivateA a2 = new ClassWithPrivateA(11);
009     a2.setOtherA(a1, 999);
010     System.out.println("a1 = " + a1.toString());
011     System.out.println("a2 = " + a2.toString());
012   }
013 }
014 
015 class ClassWithPrivateA
016 {
017   private int a;
018 
019   public ClassWithPrivateA(int a)
020   {
021     this.a = a;
022   }
023 
024   public void setOtherA(ClassWithPrivateA other, int newvalue)
025   {
026     other.a = newvalue;
027   }
028 
029   public String toString()
030   {
031     return "" + a;
032   }
033 }
Listing0906.java
Listing 9.6: Zugriff auf fremde private Membervariablen

 Hinweis 

An der Ausgabe des Programms kann man erkennen, dass über das Objekt a2 auf private Membervariablen des Objekts a1 zugegriffen wurde:

a1 = 999
a2 = 11

protected

Methoden oder Variablen vom Typ protected sind in der aktuellen Klasse und in abgeleiteten Klassen sichtbar. Darüber hinaus sind sie für Methoden anderer Klassen innerhalb desselben Pakets sichtbar. Sie sind jedoch nicht für Aufrufer der Klasse sichtbar, die in anderen Paketen definiert wurden.

public

Membervariablen und Methoden vom Typ public sind im Rahmen ihrer Lebensdauer überall sichtbar. Sie können daher in der eigenen Klasse und von beliebigen Methoden anderer Klassen verwendet werden. Das Attribut public ist zusätzlich auch bei der Klassendefinition selbst von Bedeutung, denn nur Klassen, die als public deklariert wurden, sind außerhalb des Pakets sichtbar, in dem sie definiert wurden. In jeder Quelldatei darf nur eine Klasse mit dem Attribut public angelegt werden.

Standard (package scoped)

Klassen, Methoden, Variablen mit Standard-Sichtbarkeit sind nur innerhalb des Pakets sichtbar, in dem sie definiert wurden. Sie sind beispielsweise nützlich, um in aufwändigeren Paketen allgemein zugängliche Hilfsklassen zu realisieren, die außerhalb des Pakets unsichtbar bleiben sollen. Sie können mitunter nützlich sein, um zu verhindern, dass Elemente als public deklariert werden.

static

Variablen und Methoden mit dem Attribut static sind nicht an die Existenz eines konkreten Objekts gebunden, sondern existieren vom Laden der Klasse bis zum Beenden des Programms. Das static-Attribut beeinflusst bei Membervariablen ihre Lebensdauer und erlaubt bei Methoden den Aufruf, ohne dass der Aufrufer ein Objekt der Klasse besitzt, in der die Methode definiert wurde.

Wird das Attribut static nicht verwendet, so sind Variablen innerhalb einer Klasse immer an eine konkrete Instanz gebunden. Ihre Lebensdauer beginnt mit dem Anlegen des Objekts und dem Aufruf eines Konstruktors und endet mit der Freigabe des Objekts durch den Garbage Collector.

final

Membervariablen mit dem Attribut final dürfen nicht verändert werden, sind also als Konstanten anzusehen. Methoden des Typs final dürfen nicht überlagert werden; ebenso wenig dürfen Klassen des Typs final zur Ableitung neuer Klassen verwendet werden. Wird das Attribut final dagegen nicht verwendet, sind Membervariablen veränderbar, können Methoden überlagert und Klassen abgeleitet werden.

Falls eine Methode oder Klasse das Attribut final besitzt, kann der Compiler auf die dynamische Methodensuche verzichten. final-Methoden können daher performanter aufgerufen werden als normale Methoden. Dies ist einer der Gründe dafür, dass die Java-Designer einige der mitgelieferten Klassen als final deklariert haben. Es führt aber gleichzeitig dazu, dass die entsprechenden Klassen nicht mehr erweitert werden können. Ein prominentes Beispiel aus der Laufzeitbibliothek ist die als final deklarierte Klasse String.

Seit dem JDK 1.1 kann das final-Attribut auch auf Parameter von Methoden und lokale Variablen angewendet werden. Dadurch stellt der Compiler sicher, dass die Variable bzw. der Parameter nach der Initialisierung nicht mehr verändert wird. Die Initialisierung muss dabei nicht unbedingt bei der Deklaration erfolgen, sondern kann auch später vorgenommen werden. Wichtig ist, dass nur genau einmal ein Wert zugewiesen wird.

Im Gegensatz zu C oder C++ gibt es allerdings bei als final deklarierten Objektparametern keine Möglichkeit, zwischen dem Objekt insgesamt und seinen einzelnen Elementen zu unterscheiden. Eine als final deklarierte Objektvariable wird zwar insgesamt vor Zuweisungen geschützt, der Wert einzelner Membervariablen kann jedoch verändert werden. Dies gilt analog für Arrays, die ja ebenfalls Objekte sind: final bietet keinen Schutz gegen die unerwünschte Zuweisung eines Werts an ein einzelnes Element des Arrays.

 Warnung 

transient

Membervariablen können mit dem Attribut transient belegt werden, um anzuzeigen, dass sie keine persistente Form besitzen. Sie werden beim Serialisieren und Deserialisieren von Objekten dieses Typs ignoriert. Details werden in Kapitel 42 beschrieben.

volatile

Das Schlüsselwort volatile wird verwendet, um anzuzeigen, dass Membervariablen asynchron, also außerhalb des aktuellen Threads, modifiziert werden können. Der Wert einer so deklarierten Variable wird daher bei jedem Zugriff erneut gelesen (anstatt möglicherweise direkt aus einem Register der virtuellen Maschine genommen zu werden). Die Verwendung von volatile ist eher ungebräuchlich. Es kann beispielsweise zur Sicherstellung der Datenintegrität beim Multithreading verwendet werden oder dient dazu, Zugriffe auf asynchron veränderliche Speicherstellen (etwa eine Echtzeituhr, auf die über eine Variable zugegriffen wird) stets aktuell zu halten.


 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