Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Die Funktionsbibliothek
10 Threads und nebenläufige Programmierung
11 Raum und Zeit
12 Datenstrukturen und Algorithmen
13 Dateien und Datenströme
14 Die eXtensible Markup Language (XML)
15 Grafische Oberflächen mit Swing
16 Grafikprogrammierung
17 Netzwerkprogrammierung
18 Verteilte Programmierung mit RMI und Web-Services
19 JavaServer Pages und Servlets
20 Applets
21 Midlets und die Java ME
22 Datenbankmanagement mit JDBC
23 Reflection und Annotationen
24 Logging und Monitoring
25 Sicherheitskonzepte
26 Java Native Interface (JNI)
27 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort
Download: - ZIP, ca. 12,5 MB
Buch bestellen
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> /Java-Insel | vor >>
Java ist auch eine Insel von Christian Ullenboom Programmieren mit der Java Standard Edition Version 6
Java ist auch eine Insel 7., aktualisierte Auflage geb., mit DVD (November 2007) 1.492 S., 49,90 Euro Galileo Computing ISBN 978-3-8362-1146-8 |
| 6 Eigene Klassen schreiben
|  | 6.1 Eigene Klassen mit Eigenschaften deklarieren
|  |  | 6.1.1 Attribute deklarieren
|  |  | 6.1.2 Methoden deklarieren
|  |  | 6.1.3 Die this-Referenz
|  | 6.2 Privatsphäre und Sichtbarkeit
|  |  | 6.2.1 Für die Öffentlichkeit: public
|  |  | 6.2.2 Paketsichtbar
|  |  | 6.2.3 Kein Public Viewing – Passwörter sind privat
|  |  | 6.2.4 Wieso nicht freie Methoden und Variablen für alle?
|  |  | 6.2.5 Privat ist nicht ganz privat: Es kommt darauf an, wer’s sieht
|  |  | 6.2.6 Zugriffsmethoden für Attribute deklarieren
|  |  | 6.2.7 Setter und Getter nach der JavaBeans-Spezifikation
|  | 6.3 Statische Methoden und statische Attribute
|  |  | 6.3.1 Warum statische Eigenschaften sinnvoll sind
|  |  | 6.3.2 Statische Eigenschaften mit static
|  |  | 6.3.3 Statische Eigenschaften über Referenzen nutzen?
|  |  | 6.3.4 Warum die Groß- und Kleinschreibung wichtig ist
|  |  | 6.3.5 Statische Eigenschaften und Objekteigenschaften
|  |  | 6.3.6 Statische Variablen zum Datenaustausch
|  |  | 6.3.7 Statische Blöcke als Klasseninitialisierer
|  | 6.4 Konstanten und Aufzählungen
|  |  | 6.4.1 Konstanten über öffentliche statische finale Variablen
|  |  | 6.4.2 Eincompilierte Belegungen der Klassenvariablen
|  |  | 6.4.3 Typ(un)sicherere Aufzählungen
|  |  | 6.4.4 Aufzählungen mit enum
|  | 6.5 Objekte anlegen und zerstören
|  |  | 6.5.1 Konstruktoren schreiben
|  |  | 6.5.2 Der Standard-Konstruktor
|  |  | 6.5.3 Parametrisierte und überladene Konstruktoren
|  |  | 6.5.4 Konstruktor nimmt ein Objekt vom eigenen Typ an (Copy-Konstruktor)
|  |  | 6.5.5 Einen anderen Konstruktor der gleichen Klasse aufrufen
|  |  | 6.5.6 Initialisierung der Objekt- und Klassenvariablen
|  |  | 6.5.7 Finale Werte im Konstruktor und in statischen Blöcken setzen
|  |  | 6.5.8 Exemplarinitialisierer (Instanzinitialisierer)
|  |  | 6.5.9 Ihr fehlt uns nicht – der Garbage-Collector
|  |  | 6.5.10 Implizit erzeugte String-Objekte
|  |  | 6.5.11 Private Konstruktoren, Utility-Klassen, Singleton, Fabriken
|  | 6.6 Assoziationen zwischen Objekten
|  |  | 6.6.1 Unidirektionale 1:1-Beziehung
|  |  | 6.6.2 Bidirektionale 1:1-Beziehungen
|  |  | 6.6.3 Unidirektionale 1:n-Beziehung
|  | 6.7 Vererbung
|  |  | 6.7.1 Vererbung in Java
|  |  | 6.7.2 Spielobjekte modelliert
|  |  | 6.7.3 Einfach- und Mehrfachvererbung
|  |  | 6.7.4 Sichtbarkeit protected
|  |  | 6.7.5 Konstruktoren in der Vererbung und super
|  |  | 6.7.6 Automatische und explizite Typanpassung
|  |  | 6.7.7 Das Substitutionsprinzip
|  |  | 6.7.8 Typen mit dem binären Operator instanceof testen
|  |  | 6.7.9 Methoden überschreiben
|  |  | 6.7.10 Mit super an die Eltern
|  |  | 6.7.11 Kovariante Rückgabetypen
|  |  | 6.7.12 Array-Typen und Kovarianz
|  |  | 6.7.13 Zusammenfassung zur Sichtbarkeit
|  | 6.8 Dynamisches Binden
|  |  | 6.8.1 Unpolymorph bei privaten, statischen und finalen Methoden
|  |  | 6.8.2 Polymorphie bei Konstruktoraufrufen
|  |  | 6.8.3 Finale Klassen
|  |  | 6.8.4 Nicht überschreibbare (finale) Methoden
|  | 6.9 Abstrakte Klassen und abstrakte Methoden
|  |  | 6.9.1 Abstrakte Klassen
|  |  | 6.9.2 Abstrakte Methoden
|  | 6.10 Schnittstellen
|  |  | 6.10.1 Deklarieren von Schnittstellen
|  |  | 6.10.2 Implementieren von Schnittstellen
|  |  | 6.10.3 Markierungsschnittstellen
|  |  | 6.10.4 Ein Polymorphie-Beispiel mit Schnittstellen
|  |  | 6.10.5 Die Mehrfachvererbung bei Schnittstellen
|  |  | 6.10.6 Keine Kollisionsgefahr bei Mehrfachvererbung
|  |  | 6.10.7 Erweitern von Interfaces – Subinterfaces
|  |  | 6.10.8 Vererbte Konstanten bei Schnittstellen
|  |  | 6.10.9 Schnittstellenmethoden, die nicht implementiert werden müssen
|  |  | 6.10.10 Abstrakte Klassen und Schnittstellen im Vergleich
|  | 6.11 Geschachtelte (innere) Klassen, Schnittstellen, Aufzählungen
|  |  | 6.11.1 Statische innere Klassen und Schnittstellen
|  |  | 6.11.2 Mitglieds- oder Elementklassen
|  |  | 6.11.3 Lokale Klassen
|  |  | 6.11.4 Anonyme innere Klassen
|  |  | 6.11.5 this und Vererbung
|  | 6.12 Generische Datentypen
|  |  | 6.12.1 Einfache Klassenschablonen
|  |  | 6.12.2 Einfache Methodenschablonen
|  |  | 6.12.3 Umsetzen der Generics, Typlöschung und Raw-Types
|  |  | 6.12.4 Einschränken der Typen
|  |  | 6.12.5 Generics und Vererbung, Invarianz
|  |  | 6.12.6 Wildcards
|  | 6.13 Die Spezial-Oberklasse Enum
|  |  | 6.13.1 Methoden auf Enum-Objekten
|  |  | 6.13.2 enum mit eigenen Konstruktoren und Methoden
|  | 6.14 Dokumentationskommentare mit JavaDoc
|  |  | 6.14.1 Einen Dokumentationskommentar setzen
|  |  | 6.14.2 Mit javadoc eine Dokumentation erstellen
|  |  | 6.14.3 HTML-Tags in Dokumentationskommentaren
|  |  | 6.14.4 Generierte Dateien
|  |  | 6.14.5 Dokumentationskommentare im Überblick
|  |  | 6.14.6 JavaDoc und Doclets
|  |  | 6.14.7 Veraltete (deprecated) Klassen, Konstruktoren und Methoden
## 6.2 Privatsphäre und Sichtbarkeit Innerhalb einer Klasse sind alle Funktionen und Attribute für die Methoden sichtbar. Damit die Daten und Methoden einer Klasse vor externem Zugriff geschützt oder ausdrücklich für andere wiederum als öffentlich sichtbar markiert sind, gibt es unterschiedliche Sichtbarkeiten: öffentlich geschützt paketsichtbar privat Für drei Sichtbarkeiten gibt es Schlüsselwörter, die Sichtbarkeitsmodifizierer. In diesem Kapitel sollen die Sichtbarkeiten public (öffentlich), paketsichtbar (ohne Modifizierer) und private (privat) erklärt werden; zu protected (geschützt) kommen wir beim Thema Vererbung. ### 6.2.1 Für die Öffentlichkeit: public Der Sichtbarkeitsmodifizierer public an Klassen, Konstruktoren, Methoden und sonstigen Klassen-Innereien bestimmt, dass alle diese markierten Elemente von außen sichtbar sind. Es spielt dabei keine Rolle, ob sich der Nutzer im gleichen oder in einem anderen Paket befindet. Ist zwar die Klasse public, aber eine Eigenschaft privat, kann eine fremde Klasse dennoch nicht auf die Eigenschaft zurückgreifen. Und ist eine Eigenschaft public, aber die Klasse privat, dann »kommt« eine andere Klasse erst gar nicht an diese Eigenschaft heran. ### 6.2.2 Paketsichtbar Steht kein ausdrücklicher Sichtbarkeitsmodifizierer, gilt die Paketsichtbarkeit. Sie sagt aus, dass die paketsichtbaren Klassen nur von anderen Klassen im gleichen Paket gesehen werden können. Für die Eigenschaften gilt das Gleiche: Nur Typen im gleichen Paket sehen die paketsichtbaren Eigenschaften. Dazu einige Beispiele. Zwei Klassen A und B befinden sich in unterschiedlichen Paketen. Die Klasse A ist nicht öffentlich. Listing 6.8 com/tutego/insel/protecteda/A.java
    package com.tutego.insel.protecteda;
    class A
    {
    }
Die Klasse B versucht, sich auf A zu beziehen, doch funktioniert das wegen der »Unsichtbarkeit« von A nicht – es gibt einen Compilerfehler. Listing 6.9 com/tutego/insel/protectedb/B.java
    package com.tutego.insel.protectedb;
    class B
    {
      A a;            // A cannot be resolved to a type
    }
Ist eine Klasse C öffentlich, aber die Klasse deklariert ein nur paketsichtbares Attribut c, dann kann eine Klasse in einem anderen Paket das Attribut nicht sehen, auch wenn sie die Klasse selbst sehen kann. Listing 6.10 com/tutego/insel/protecteda/C.java
    package com.tutego.insel.protecteda;
    public class C
    {
      int c;
    }
Und die Klasse D: Listing 6.11 com/tutego/insel/protecteda/C.java
    package com.tutego.insel.protectedb;
    import com.tutego.insel.protecteda.C;
    class D
    {
      int d = C.c;    // The field C.c is not visible
    }
Paketsichtbare Eigenschaften sind sehr nützlich, weil sich damit Gruppen von Typen bilden lassen, die gegenseitig Teile ihres Innenlebens kennen. Von außerhalb des Pakets ist der Zugriff auf diese Teile dann untersagt, analog zu private. Dazu ein Beispiel für unsere Spielerklasse. Nutzt der Player zum Beispiel intern eine Hilfsklasse, etwa zur Speicherung der Gegenstände, so kann diese paketsichtbare Speicherklasse für Außenstehende unsichtbar bleiben. ### 6.2.3 Kein Public Viewing – Passwörter sind privat Der Sichtbarkeitsmodifizierer private verbietet allen von außen zugreifenden Klassen den Zugriff auf Eigenschaften. Das wäre etwa für eine Klasse wichtig, die Passwörter speichern möchte. Dafür wollen wir eine Klasse Password mit einem privaten Attribut pass deklarieren. Eine öffentliche Methode setPassword() soll eine Änderung des Passwortes zulassen, wenn das alte Passwort bekannt ist. Am Anfang ist das Passwort der leere String. Listing 6.12 Password.java
    class Password
    {
      private String pass = "";

      public void setPassword( String oldpass, String newpass )
      {
        if ( oldpass != null && oldpass.equals(pass) )
        {
          pass = newpass;
          System.out.println( "Passwort gesetzt." );
        }
        else
          System.out.println( "Passwort konnte nicht gesetzt werden." );
      }
    }
Wir sehen, dass öffentliche Objektmethoden ganz selbstverständlich auf das private-Element ihrer Klasse zugreifen können. Hier klicken, um das Bild zu vergrößern Abbildung 6.1 In der UML werden private Eigenschaften mit einem führenden Minus gekennzeichnet. Eine zweite Klasse PasswordDemo will nun auf das Passwort von außen zugreifen. Listing 6.13 PasswordDemo.java
    public class PasswordDemo
    {
      public static void main( String[] args )
      {
        Password pwd = new Password();
        pwd.setPassword( "", "TeutoburgerWald" );
        pwd.setPassword( "TeutoburgerWald", "Doppelkeks" );
        pwd.setPassword( "Dopplerkeks", "panic" );
        //    System.out.println( pwd.pass );   // Compilerfehler
      }
    }
Die Klasse Password enthält den privaten String pass, und dieser kann nicht referenziert werden. Der Compiler erkennt zur Übersetzungs- beziehungsweise Laufzeit Verstöße und meldet diese. Bei einem durch die falsche Sichtbarkeit verursachten Fehler bietet Eclipse mit + eine Änderung der Sichtbarkeit an. Hier klicken, um das Bild zu vergrößern Allerdings wäre es manchmal besser, wenn der Compiler uns nicht verraten würde, dass das Element privat ist, sondern einfach nur melden würde, dass es dieses Element nicht gibt. ### 6.2.4 Wieso nicht freie Methoden und Variablen für alle? Private Funktionen und Variablen dienen in erster Linie dazu, den Klassen Modularisierungsmöglichkeiten zu geben, die von außen nicht sichtbar sein müssen. Zwecks Strukturierung werden Teilaufgaben in Funktionen gegliedert, die aber von außen nie allein aufgerufen werden dürfen. Da die Implementierung versteckt wird und der Programmierer vielleicht nur eine Zugriffsfunktion sieht, wird auch der Terminus »Data Hiding« verwendet. Wer wird schon einem Fremden die Geheimzahl der Kreditkarte geben oder verraten, mit wem er die letzte Nacht verbracht hat? Oder nehmen wir zum Beispiel ein Radio. Von außen bietet es die Funktionen an(), aus(), lauter() und leiser() an, aber welche physikalischen Vorgänge ein Radio dazu bringt, Musik zu spielen, ist eine ganz andere Frage, für die wir uns als gewöhnliche Benutzer eines Radios nicht interessieren. Der Einsatz von private zeigt sich besonders in Unterklassen, denn wenn in einer Oberklasse Eigenschaften mit private gekennzeichnet werden, ist der Zugriff auf diese Funktionen in der Unterklasse nicht erlaubt. Interessieren diese Informationen auch manche Unterklassen, lassen sich die Methoden und Attribute protected deklarieren. Damit räumt eine Oberklasse den Unterklassen spezielle Privilegien ein. Mit protected sind die Mitglieder einer Klasse für die Unterklassen sichtbar und ebenso im gesamten Paket. ### 6.2.5 Privat ist nicht ganz privat: Es kommt darauf an, wer’s sieht Private Eigenschaften sind nur für andere Klassen privat, aber nicht für die eigene, auch wenn die Objekte unterschiedlich sind. Das ist eine Art Spezialfall, dass über eine Referenzvariable der Zugriff auf eine private Eigenschaft erlaubt ist. Listing 6.14 Key.java
    public class Key
    {
      private int id;

      boolean compare( Key that )
      {
        return this.id == that.id;
      }
    }
Die Methode compare() der Klasse Key vergleicht das eigene Attribut this.id mit dem Attribut des als Argument übergebenen Objekts that.id. (Zwar wäre this nicht nötig, doch verdeutlicht es schön das eigene und das fremde Objekt.) An dieser Stelle sehen wir, dass der Zugriff auf that.id zulässig ist, obwohl id privat ist. Dieser Zugriff ist aber erlaubt, da die compare()-Methode in der Key-Klasse deklariert und der Parameter ebenfalls vom Typ Key ist. Mit Unterklassen funktioniert das schon nicht mehr. Private Attribute und Methoden sind also gegen Angriffe von außerhalb der deklarierenden Klasse geschützt. ### 6.2.6 Zugriffsmethoden für Attribute deklarieren Attribute sind eine tolle und notwendige Sache. Allerdings ist zu überlegen, ob der Nutzer eines Objekts immer direkt auf die Attribute zugreifen sollte, oder ob dies problematisch ist.
1. | Bei manchen Variablen gibt es Wertebereiche, die einzuhalten sind. Das Alter eines Spielers kann nicht kleiner null sein, und Menschen, die älter als zweihundert Jahre sind, werden nur in der Bibel genannt. Wenn wir das Alter privat machen, kann eine Zugriffsfunktion wie setAge(int) mit Hilfe einer Bereichsprüfung nur bestimmte Werte in die Objektvariable übertragen und den Rest ablehnen. Die öffentliche Methode getAge() gibt dann Zugriff auf die Variable.
2. | Mit einigen Variablen sind Abhängigkeiten verbunden. Wenn zum Beispiel ein Spieler ein Alter hat, kann der Spieler gleichzeitig eine Wahrheitsvariable für die Volljährigkeit deklarieren. Natürlich gibt es nun eine Abhängigkeit. Ist der Spieler älter als 18, soll die Wahrheitsvariable auf true stehen. Diese Abhängigkeit lässt sich mit zwei öffentlichen Variablen nicht wirklich erzwingen. Eine Methode setAge(int) kann jedoch bei privaten Attributen diese Konsistenz einhalten.
3. | Gibt es Zugriffsmethoden, so lassen sich dort leicht Debug-Breakpoints setzen. Auch lassen sich die Methoden so erweitern, dass der Zugriff geloggt (protokolliert) wird oder die Rechte des Aufrufers geprüft werden.
4. | Bei Klassen gilt das Geheimnisprinzip. Obwohl es vorrangig für Methoden gilt, sollte es auch für Variablen gelten. Möchten Entwickler etwa ihr internes Attribut von int auf BigInteger ändern und damit beliebig große Ganzzahlen verwalten, hätten wir ein beträchtliches Problem, da an jeder Stelle des Vorkommens ein Objekt eingesetzt werden müsste. Wollten wir zwei Variablen einführen, ein int, damit die alte, derzeit benutzte Software ohne Änderung auskommt, und ein neues BigInteger, hätten wir ein Konsistenzproblem.
5. | Nicht immer müssen dem Aufrufer haarklein alle Eigenschaften angeboten werden. Der Nutzer möchte so genannte höherwertige Dienste vom Objekt angeboten bekommen, sodass der Zugriff auf die unteren Attribute vielleicht gar nicht nötig ist.
### 6.2.7 Setter und Getter nach der JavaBeans-Spezifikation Wir sehen an diesen Beispielen, dass es gute Gründe dafür gibt, Attribute zu privatisieren und öffentliche Methoden zum Lesen und Schreiben anzubieten. Weil diese Methoden auf die Attribute zugreifen, nennen sie sich auch Zugriffsmethoden. Für jedes Attribut wird eine Schreib- und Lesemethode deklariert, für die es auch ein festes Namensschema laut JavaBean-Konvention gibt. Die Zugriffsmethoden machen dabei eine Property zugänglich. Für eine Property »name« und den Typ String gilt zum Beispiel: String getName(). Die Methode besitzt keine Parameterliste, und der Rückgabetyp ist String. void setName(String name). Die Methode hat keine Rückgabe, aber genau einen Parameter. Die getXXX()-Methoden heißen Getter, die setXXX()-Methoden Setter. Die Methoden sind öffentlich und der Typ der Getter-Rückgabe muss der gleiche wie der Parametertyp vom Setter sein. Bei boolean-Attributen darf es (und muss es in manchen Fällen auch) statt getXXX() alternativ isXXX() heißen. (Da die Programmentwicklung in der Regel mit englischen Bezeichnernamen erfolgt, kommt es nicht zu unschönen Bezeichnernamen à la getGegenstand() oder isVolljähfig().) #### Zugriffsmethoden für den Spieler Das folgende Beispiel soll einen Spieler umsetzen, bei dem Name und Gegenstand privat und hübsch durch Zugriffsfunktionen abgesichert sind. Eine Konsistenzprüfung soll verhindern, dass ein String null oder leer ist. Listing 6.15 com/tutego/insel/game/v5/Player.java, Player
    class Player
    {
      private String name = "";
      private String item = "";

      public String getName()
      {
        return name;
      }

      public void setName( String name )
      {
        if ( name != null && name.length() >= 0 )
          this.name = name;
      }

      public String getItem()
      {
        return item;
      }

      public void setItem( String item )
      {
        if ( item != null && item.length() >= 0 )
          this.item = item;
      }
    }
Es muss keine gute Idee sein, sich bei ungültigen Werten taub zu stellen; eine Alternative besteht darin, zu loggen, oder etwa in Form einer Ausnahme (Exception) unerwünschte Werte zu melden. Der Nutzer der Klasse muss wegen der Methodenaufrufe etwas mehr schreiben: Listing 6.16 com/tutego/insel/game/v5/Playground.java
    Player spongebobby = new Player();
    spongebobby.setName( "Spongebobby" );
    spongebobby.setItem( "snail" );
Wird später bei der Weiterentwicklung des Programms eine Änderung nötig, wenn etwa die Gegenstände anders gespeichert werden sollen, kann der Typ der internen Variable geändert werden, und die Welt draußen bekommt davon nichts mit. Lediglich intern in den Gettern und Settern ändert sich etwas, aber nicht an der Schnittstelle. Eclipse bietet zwei Möglichkeiten, Setter und Getter automatisch zu generieren. Das Kontextmenü unter Source • Generate Getters and Setters... fördert ein Dialogfenster zu Tage, mit dem Eclipse automatisch die setXXX()- und getXXX()-Methoden einfügen kann. Die Attribute, für die eine Zugriffsmethode gewünscht ist, werden selektiert. Die zweite Möglichkeit funktioniert nur für genau ein Attribut. Steht der Cursor auf der Variable, liefert Refactor • Encapsulate Field... einen Dialog, mit dem Setter und Getter zum einen generiert und zum anderen die direkten Zugriffe auf das Attribut in Funktionsaufrufe umgewandelt werden. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.
Name |
E-Mail |
Ihr Kommentar |
<< zurück | <top> | vor >>

Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de