Packages und Imports
Java ist eine professionelle Programmiersprache und wird benutzt um sehr grosse Anwendungen zu schreiben. Mit grossen Anwendungen meinen wir Programme, die aus tausenden von verschiedenen Klassen bestehen. Dies ist nur möglich, weil Java auch die entsprechenden Konstrukte zur Verfügung stellt um diese in logische Einheiten zu organisieren. Das für uns wichtigste dieser Konstrukte sind Packages. Neben Packages gibt es noch das Konzept der Module, welche zur Strukturierung genutzt werden. Da diese aber erst für richtig grosse Anwendungen gebraucht werden, die selbst wieder aus vielen Packages bestehen, werden wir diese in dieser Vorlesung nicht behandeln und uns ganz auf Packages fokussieren.
Packages
Der grundlegende Mechanismus um Klassen in Java zu organisieren wird über das Dateisystem realisiert. Zusammengehörende Klassen werden einfach in dasselbe Verzeichnis geschrieben. Der Name des Package entspricht dem Namen des Verzeichnis. Damit Java diese Konvention auch durchsetzen und überprüfen und nutzen kann, muss zusätzlich der Name des Package im Quellcode angegeben werden.
Wir illustrieren dies an einem Beispiel:
Angenommen wir haben drei Klassen A1
, A2
und B1
.
Wir möchten, dass die Klassen A1
und A2
Teil eines Packages mit dem Namen foo
sind.
Die Klassen B
soll ein Teil eines Packages mit dem Namen bar
sein.
Wir hätten folgende Dateien und Verzeichnisse in unserem Projekt:
./src/foo/A1.java
./src/foo/A2.java
./src/bar/B1.java
Wir haben dabei alle Dateien in einem gemeinsamen Oberverzeichnis mit dem Namen src
gespeichert.
Die Quelldateien würden dann wie folgt aussehen:
package foo; // Paketdefintion, am Anfang der Datei
class A1 {
// Implementation der Klasse
}
package foo; // Paketdefintion, am Anfang der Datei
class A2 {
// Implementation der Klasse
}
package bar; // Paketdefintion, am Anfang der Datei
class B1 {
// Implementation der Klasse
}
Hierarchien
Genau wie Verzeichnisse im Dateisystem wieder andere Verzeichnisse enthalten können, können auch Packages wieder Packages enthalten. Der Mechanismus in Java wird einfach logisch fortgesetzt. Die Klassen in den einzelnen Unterpackages werden dabei in das entsprechende Unterverzeichnis geschrieben.
Achtung: Der Paketname wird nicht durch einen Slash
/
getrennt, sondern durch einen Punkt.
Im folgenden Beispiel haben wir weitere Klassen neben A1
und A2
im Verzeichnis foo
hinzugefügt.
Die Klassen A31
und A41
liegen in den Packages foo.sub1
respektive foo.sub2
.
./src/foo/A1.java
./src/foo/A2.java
./src/foo/sub1/A31.java
./src/foo/sub2/A41.java
Die entsprechenden Quellcodedateien sehen wie folgt aus:
package foo.sub1;
class A31 {
// Implementation der Klasse
}
package foo.sub2;
class A41 {
// Implementation der Klasse
}
Packages als Namesräume
Durch die Anordnung in Packages haben wir den Klassen nun auch neue Namen gegeben.
Die Klasse A1
im obigen Beispiel hat nun den vollen Namen foo.A1
.
Die Klasse A31
hat den Namen foo.sub1.A31
.
Damit wird es möglich, denselben Klassennamen in verschiedenen Packages zu nutzen.
Durch den vollen Namen können diese voneinander unterschieden werden.
In grossen Programmen, mit zehntausenden von Klassen, ist dies enorm wichtig.
Die Programmierer*innen können sich auf das Paket konzentrieren, indem sie gerade arbeiten.
Sie können einen möglichst sinnvollen Klassennamen im aktuellen Paket wählen.
Es kommt zu keinen Problemen mit Namen von Klassen in anderen Packages.
Der Preis, den wir dafür zahlen ist, dass jetzt der Name der Klasse länger geworden ist.
Wenn wir zum Beispiel im der Klasse B1
zwei Felder der Klasse A31
und A32
erstellen wollen, würden wir Folgendes schreiben:
package bar;
class B1 {
// Felder
foo.sub1.A31 field1;
foo.sub2.A32 field2;
B1() {
this.field1 = new foo.sub1.A31();
this.field2 = = new foo.sub2.A32();
}
}
Dies ist etwas lang und wirkt sperrig. Java bietet zwei Möglichkeiten für Vereinfachungen:
- Wenn kein Packagename angegeben wird (also der Name keinen Punkt enthält) nimmt Java an, dass die Klasse im aktuellen Package vorhanden ist. Das bedeutet, wir müssen nur Klassen qualifizieren, die in einem anderen Package definiert sind.
- Wir können Klassen durch die Importklausel über einen kürzeren Namen verfügbar machen.
Importieren von Klassen
Damit wir Klassen aus anderen Paketen auch direkt über den Klassennamen ansprechen können, müssen wir diese importieren.
Dafür stellt Java das Schlüsselwort import
zur Verfügung.
Nach dem Schlüsselwort import
können wir den vollen Klassennamen (also Klassennamen mit Packagename) hinschreiben.
Danach lässt uns Java diese Klasse direkt über den Klassennamen ansprechen.
package bar;
import foo.sub1.A31;
import foo.sub2.A32;
class B1 {
// Felder
A31 field1;
A32 field2;
B1() {
this.field1 = new A31();
this.field2 = = new A32();
}
}
Falls wir aus einem Paket alle darin definierten Klassen importieren möchten, können wir das Zeichen *
als Wildcard benutzen.
Die Anweisung import foo.sub1.*
importiert also alle Klassen aus dem Paket foo.sub1
.
Anwendung: Bibliotheken in Java
Wenn wir Programme in Java schreiben, dann programmieren wir typischerweise nicht die gesamte Funktionalität selbst, sondern nutzen Bibliotheken.
Bibliotheken in Java sind nichts anderes als eine Sammlung von Klassen, die in einem oder mehreren Paketen organisiert sind.
So stellt uns Java zum Beispiel die Klasse ArrayList
zur Verfügung, die eine flexiblere Implementation eines Arrays darstellt.
Wir können diese über die import-Anweisung wie folgt importieren:
import java.utils.ArrayList
Wir wissen nun, dass diese Klasse in einem Paket java.util
liegt.
Java stellt uns viele solcher Pakete zur Verfügung: Einen Überblick über die wichtigsten finden Sie in der Java API-Dokumentation.
Randbemerkung: Module
Wie bereits angemerkt bietet Java noch eine zusätzliche Funktionalität, um Programme zu organisieren.
Diese werden Module genannt.
Jedes Modul beinhaltet eine Sammlung von Paketen.
Die oben gezeigten Pakete in der API-Dokumentation befinden sich alle im Module java.base
.
Es gibt jedoch noch eine Vielzahl anderer Module.
Diese bestehen dann auch wieder aus dutzenden von Paketen mit hunderten von Klassen.
Welche Module in der aktuellen Java Version zur Verfügung stehen, können Sie auch in der Java API-Dokumentation nachschauen.
Da Sie auf absehbare Zeit keine so grossen Programme schreiben werden und mit diesem Mechanismus auch nicht direkt in Berührung kommen werden, werden wir Module in diesem Kurs nicht diskutieren.
Haben Sie Fragen oder Bemerkungen? Schreiben Sie diese doch ins Forum.