Galileo Computing < openbook >
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.


Java ist auch eine Insel von Christian Ullenboom
Buch: Java ist auch eine Insel (Galileo Computing)
gp Kapitel 6 Eigene Klassen schreiben
gp 6.1 Eigene Klassen definieren
gp 6.1.1 Methodenaufrufe und Nebeneffekte
gp 6.1.2 Argumentübergabe mit Referenzen
gp 6.1.3 Die this-Referenz
gp 6.1.4 Überdeckte Objektvariablen nutzen
gp 6.2 Assoziationen zwischen Objekten
gp 6.3 Pakete
gp 6.3.1 Hierarchische Strukturen
gp 6.3.2 Paketnamen
gp 6.3.3 Eine Verzeichnisstruktur für eigene Projekte
gp 6.4 Privatsphäre und Sichtbarkeit
gp 6.4.1 Wieso nicht freie Methoden und Variablen für alle?
gp 6.4.2 Privat ist nicht ganz privat. Es kommt darauf an, wer's sieht
gp 6.4.3 Zugriffsmethoden für Attribute definieren
gp 6.4.4 Zusammenfassung zur Sichtbarkeit
gp 6.4.5 Sichtbarkeit in der UML
gp 6.5 Statische Methoden und Variablen
gp 6.5.1 Warum statische Eigenschaften sinnvoll sind
gp 6.5.2 Statische Eigenschaften mit static
gp 6.5.3 Statische Eigenschaften als Objekteigenschaften nutzen
gp 6.5.4 Statische Eigenschaften und Objekteigenschaften
gp 6.5.5 Statische Variablen zum Datenaustausch
gp 6.5.6 Warum die Groß- und Kleinschreibung wichtig ist
gp 6.5.7 Konstanten mit dem Schlüsselwort final bei Variablen
gp 6.5.8 Problem mit finalen Klassenvariablen
gp 6.5.9 Typsicherere Konstanten
gp 6.5.10 Statische Blöcke
gp 6.6 Objekte anlegen und zerstören
gp 6.6.1 Konstruktoren schreiben
gp 6.6.2 Einen anderen Konstruktor der gleichen Klasse aufrufen
gp 6.6.3 Initialisierung der Objekt- und Klassenvariablen
gp 6.6.4 Finale Werte im Konstruktor setzen
gp 6.6.5 Exemplarinitialisierer (Instanzinitialisierer)
gp 6.6.6 Zerstörung eines Objekts durch den Müllaufsammler
gp 6.6.7 Implizit erzeugte String-Objekte
gp 6.6.8 Zusammenfassung: Konstruktoren und Methoden
gp 6.7 Veraltete (deprecated) Methoden/Konstruktoren
gp 6.8 Vererbung
gp 6.8.1 Vererbung in Java
gp 6.8.2 Einfach- und Mehrfachvererbung
gp 6.8.3 Gebäude modelliert
gp 6.8.4 Konstruktoren in der Vererbung
gp 6.8.5 Sichtbarkeit
gp 6.8.6 Das Substitutionsprinzip
gp 6.8.7 Automatische und explizite Typanpassung
gp 6.8.8 Finale Klassen
gp 6.8.9 Unterklassen prüfen mit dem Operator instanceof
gp 6.8.10 Methoden überschreiben
gp 6.8.11 super: Aufrufen einer Methode aus der Oberklasse
gp 6.8.12 Nicht überschreibbare Funktionen
gp 6.8.13 Fehlende kovariante Rückgabewerte
gp 6.9 Die oberste aller Klassen: Object
gp 6.9.1 Klassenobjekte
gp 6.9.2 Objektidentifikation mit toString()
gp 6.9.3 Objektgleichheit mit equals() und Identität
gp 6.9.4 Klonen eines Objekts mit clone()
gp 6.9.5 Hashcodes
gp 6.9.6 Aufräumen mit finalize()
gp 6.9.7 Synchronisation
gp 6.10 Die Oberklasse gibt Funktionalität vor
gp 6.10.1 Dynamisches Binden als Beispiel für Polymorphie
gp 6.10.2 Keine Polymorphie bei privaten, statischen und finalen Methoden
gp 6.10.3 Polymorphie bei Konstruktoraufrufen
gp 6.11 Abstrakte Klassen
gp 6.11.1 Abstrakte Klassen
gp 6.11.2 Abstrakte Methoden
gp 6.11.3 Über abstract final
gp 6.12 Schnittstellen
gp 6.12.1 Ein Polymorphie-Beispiel mit Schnittstellen
gp 6.12.2 Die Mehrfachvererbung bei Schnittstellen
gp 6.12.3 Erweitern von Interfaces - Subinterfaces
gp 6.12.4 Vererbte Konstanten bei Schnittstellen
gp 6.12.5 Vordefinierte Methoden einer Schnittstelle
gp 6.12.6 CharSequence als Beispiel einer Schnittstelle
gp 6.13 Innere Klassen
gp 6.13.1 Statische innere Klassen und Schnittstellen
gp 6.13.2 Mitglieds- oder Elementklassen
gp 6.13.3 Lokale Klassen
gp 6.13.4 Anonyme innere Klassen
gp 6.13.5 Eine Sich-Selbst-Implementierung
gp 6.13.6 this und Vererbung
gp 6.13.7 Implementierung einer verketteten Liste
gp 6.13.8 Funktionszeiger
gp 6.14 Gegenseitige Abhängigkeiten von Klassen


Galileo Computing

6.3 Paketedowntop

Ein Paket ist eine Gruppe von thematisch zusammengehörigen Klassen, die sich normalerweise1 in einem Verzeichnis befinden. Den Verzeichnisnamen gibt ein Paketname an. Nehmen wir folgende Verzeichnisstruktur an:

suessigkeiten/
suessigkeiten/Zucker.java
suessigkeiten
/Schokolade.java

Die Definition der Klasse Zucker enthält als oberstes eine package-Anweisung, die sie dem Paket suessigkeiten zuordnet.

package suessigkeiten;
public class Zucker
{
 ...
}

Das Gleiche gilt auch für die Schokolade im gleichen Paket.

package suessigkeiten;
public class Schokolade extends Zucker
{
 ...
}

Um Klassen innerhalb von Paketen nutzen zu können, müssen sie dem Compiler präzise beschrieben werden. Dazu gibt es zwei Möglichkeiten. Zum einen lassen sich die Klassen (oder Schnittstelle) voll qualifizieren.

suessigkeiten.Schokolade s = new süßigkeiten.Schokolade();

Eine alternative und praktischere Möglichkeit ist, dem Compiler in einer Klassendefinition mit import auf die Klassen im Paket aufmerksam gemacht.

import suessigkeiten.Schokolade;

class Weihnachtsmann
{
  Schokolade s;    // sonst suessigkeiten.Schokolade
}

Da die Klassen Schokolade und Zucker im gleichen Paket liegen, muss bei der Verwendung in der Vererbung die Klasse Zucker nicht extra bekannt gemacht werden.

Damit nicht alle Klassen eines Pakets einzeln aufgeführt werden müssen, lässt sich mit dem Sternchen als einer Art Wildcard auf alle sichtbaren Klassen zugreifen.

Ein Problem gibt es bei mehreren gleich benannten Klassen in verschiedenen Paketen. Hier ist eine volle Qualifizierung nötig. Ab dem SDK 1.2 gibt es im Paket java.awt und java.util eine Liste. Ein einfaches import java.awt.* und java.util.* hilft da nicht, denn der Compiler weiß nicht, ob die GUI-Komponente oder die Datenstruktur gemeint ist. Auch sagt ein import nichts darüber aus, ob die Klassen in der importierenden Datei jemals gebraucht werden. Das gleicht gilt für die Klasse Date, die einmal in java.util und einmal in java.sql zu finden ist. Lustigerweise erweitert java.sql.Date die Klasse java.util.Date. Dass der Compiler hier nicht durcheinander kommt, ist ganz einfach dadurch zu erklären, dass er die Klassen nicht nur durch ihren Namen unterscheidet, sondern viel mehr auch durch ihre Pakete. Der Compiler betrachtet intern immer eine volle Qualifizierung.


Galileo Computing

6.3.1 Hierarchische Strukturendowntop

Pakete sind oft in Hierarchien geordnet. Dies wird auch durch die Abbildung auf die Verzeichnisstruktur des Dateisystems deutlich. Daher gehören zu einem Paket oft verschiedene Unterpakete. Es werden durch import java.* nicht automatisch alle Klassen der Unterpakete mit eingebunden. Die import-Anweisung bezieht sich nur auf ein Verzeichnis und schließt die Unterverzeichnisse nicht mit ein.

Falls eine Klasse ohne Paket-Definition implementiert wird, so befindet sie sich standardmäßig im umbenannten Paket (engl. unnamed package), oder Default-Paket. Es ist eine gute Idee, eigene Klassen immer in Paketen zu organisieren. Das erlaubt auch feinere Sichtbarkeiten.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 6.3 Eclipse sieht für das unbekannte Paket ein »virtuelles« Verzeichnis vor. Es nennt sich default package.


Galileo Computing

6.3.2 Paketnamendowntop

Prinzipiell kann ein Paketname beliebig sein, doch Hierarchien bestehen in der Regel aus umgedrehten Domänennamen. Aus der Domäne zur Webseite http://javatutor.com wird also com.java-tutor. Diese Namensgebung gewährleistet, dass Klassen auch weltweit eindeutig bleiben. Ein Paketname wird in aller Regel komplett kleingeschrieben.

Die Paketnamen java, javax und sun

Sun hat für sich selbst einige Paketnamen reserviert, die von eigenen Klassen nicht genutzt werden sollen. So liegt unser java.awt.Point in einem Sun-Paket und das ist leicht durch den Teil java zu erkennen. Wenn jemand eigene Klassen in Pakete mit dem Präfix java setzen würde, etwa java.gui, der erzeugt damit Verwirrung, denn es ist nicht mehr erkennbar, ob das Paket bei jeder Distribution dabei ist - wie dies für die Sun-Klassen der Fall ist.


Galileo Computing

6.3.3 Eine Verzeichnisstruktur für eigene Projektetoptop

Neben der Einteilung in Paketen für das eigene Programm, ist es auch sinnvoll, die gesamte Applikation in verschiedenen Verzeichnissen aufzubauen. Im Allgemeinen finden sich drei wichtige Hauptverzeichnisse: src für die Quellen, lib für externe Bibliotheken auf die das Programm aufbaut und bin (oder build) für die erzeugen Klassen-Dateien. Das Verzeichnis src lässt sich noch weiter unterteilen, etwa für Quellen, die Testfälle implementieren oder Beispiele.

src/
 core/
 examples/
 test/
lib/
bin/





1 Ich schreibe »normalerweise«, da die Paketstruktur nicht zwingend auf Verzeichnisse abgebildet werden muss. Pakete könnten beispielsweise vom Klassenlader aus einer Datenbank gelesen werden.





Copyright (c) Galileo Press GmbH 2004
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 GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de