Einzelne Klassen können zu Paketen (engl. packages) zusammengefasst
werden. Die Klassen werden dann auch als Mitglieder (engl. members) des Pakets
bezeichnet. Um eine Klasse einem bestimmten Paket zuzuordnen, kann innerhalb
des Java-Quelltextes das Schlüsselwort package
verwendet werden.
Die package
-Angabe wird vor der eigentlichen Deklaration der
Klasse notiert. Nach dem Schlüsselwort folgt dann der gewählte Name des Pakets.
package PaketName;
Das anschließende Listing deklariert die Klasse PackageExample1
.
Direkt zu Beginn folgt nach package
der gewählte Name des Pakets
p1
. Die Beispielklasse ist also durch diese Angabe Mitglied
des Pakets p1
.
Listing 1.18. PackageExample1.java
. Die Klasse PackageExample1
wird dem Paket p1
zugeordnet.
package p1;
public class PackageExample1 {
public static int a1 = 3;
public static void method11() {
System.out.println("method11");
}
}
Pakete bzw. die darin enthaltenen Klassen können innerhalb des Dateisystems
in Ordnern bzw. Unterordnern organisiert werden. Ein Paketname wird in ein
korrespondierendes Dateiverzeichnis transformiert, in dem die Quell- und
Klassendateien lokalisiert sind. Ausgehend von einem gewählten Ausgangsverzeichnis
erzwingt die package
-Angabe im Beispiel einen Unterordner mit
dem Namen p1
. In diesen Ordner kann dann die Datei
PackageExample1.java
kopiert werden.
Ausgangsverzeichnis/p1: PackageExample1.java
Auch weitere Klassen, die mit package p1
diesem Paket
zugeordnet werden sollen, können in diesen speziellen Unterordner kopiert werden.
Im Ordner p1
sind also alle Klassen enthalten bzw. organisiert,
die Bestandteil des Pakets p1
sind.
Im Zusammenhang mit Paketen wird auch von einem voll qualifizierten
Namen einer Klasse gesprochen. Im Beispiel ist der voll qualifizierte
Name der deklarierten Klasse p1.PackageExample1
. Der verwendete
Paketname wird also dem Klassennamen vorangestellt und die beiden
Namensbezeichnungen sind durch einen Punkt voneinander getrennt.
Paket im Paket
Ein Paket kann Teil eines anderen Pakets sein. Ein Paket kann also auch
weitere Unterpakete besitzen. Soll z.B. eine Klasse innerhalb eines Unterpakets
angeordnet sein, könnte die im Quelltext verwendete package
-Angabe
den folgenden Aufbau besitzen:
package PaketName1.PaketName2;
Der folgende Quelltext enthält eine derartig aufgebaute
package
-Angabe. Dies hat zur Folge, dass die Klasse
PackageExample2
dem Paket p2
zugeordnet wird.
p2
ist wiederum Unterpaket von p1
.
Listing 1.19. PackageExample2.java
. Das Paket p2
ist Teil
des Pakets p1
.
package p1.p2;
public class PackageExample2 {
public int a2 = 4;
public void method21() {
System.out.println("method21");
}
}
Entsprechend der Paket-Konvention wäre demnach die Datei
PackageExample2.java
, ausgehend von einem gewählten
Ausgangsverzeichnis, im Unterordner p1/p2
abzuspeichern.
Ausgangsverzeichnis/p1/p2: PackageExample2.java
Das Default-Paket
Es ist nicht verpflichtend, eine Klasse in ein Paket zu packen. D.h.
die Verwendung des Schlüsselwortes package
ist nicht notwendig.
Eine Klasse, die nicht explizit einem Paket zugeordnet wurde, befindet sich
per Vorgabe automatisch im sogenannten Default-Paket
(unnamed package). Bei der Erstellung von kleineren
Programmen wird oft auf eine Paketzuordnung der beteiligten Klassen verzichtet.
Bei größeren Anwendungen ist die Strukturierung der erstellten Klassen durch
die Verwendung von Paketen allerdings oft unverzichtbar.
Eindeutige Paketnamen
In Listing 1.19 ist der voll qualifizierte Name
der Unterpakets p1.p2
. Bei größeren Softwareprojekten wird versucht,
Paketen einen eindeutigen Namen zu geben. Einzelne Pakete werden mitunter weltweit
genutzt und die Wahrscheinlichkeit, dass ein weiteres Paket ebenfalls den
Namen p1.p2
hat ist natürlich groß - dies führt zu Verwechslungen
und ein Paket kann nicht eindeutig, z.B. einem bestimmten Softwareersteller,
zugeordnet werden. Es wird deshalb vorgeschlagen Internet-Domainnamen zu benutzen,
um eine eindeutige Namensbezeichnung von Paketen zu gewährleisten.
Der Beispiel-Domainname javaseiten.de
kann dazu umgekehrt werden
zu de.javaseiten
. Die Top-Level-Domain de
wird
zuerst notiert, anschließend folgt die Second-Level-Domain
javaseiten
. Um die in den vorangehenden Beispielen verwendeten
Paketnamen p1
und p2
in eindeutiger Weise festzulgen,
könnten diese mit den folgenden voll qualifizierten Namen notiert werden:
de.javaseiten.p1
de.javaseiten.p1.p2
Diese Paketnamen, bei denen der Domainname verwendet wurde, erfordern
eine entsprechende package
-Angabe in den Java-Quelltexten:
/* PackageExample1.java */
package de.javaseiten.p1;
...
/* PackageExample2.java */
package de.javaseiten.p1.p2;
...
Da die package
-Angaben im Quelltext direkt mit einer
entsprechenden Ordnerstruktur korrespondieren, ist eine dem Paketnamen angepasste
Ordnerstruktur notwendig. Die im Beispiel verwendeten Quelltextdateien
PackageExample1.java
und PackageExample2.java
,
die den einzelnen Paketen angehören, müssten dann innerhalb der folgendn
Ordnerstruktur angeordnet sein.
Ausgangsverzeichnis/de/javaseiten/p1: PackageExample1.java
Ausgangsverzeichnis/de/javaseiten/p1/p2: PackageExample2.java
1.5.2. Importieren von Klassen und Paketen
Mit Hilfe des Schlüsselwortes import
können einzelne
Klassen aus bestimmten Paketen oder ganze Pakete "importiert" werden. Die
Bezeichnung "importieren" ist in dem Sinne zu verstehen, dass z.B. eine
Klasse durch die Angabe ihres einfachen Namens genutzt werden kann. Ohne eine
import
-Angabe zu Beginn eines Quelltextes müsste eine Klasse, die
sich z.B. im Paket p1
befindet, mit ihrem voll qualifizierten
Namen adressiert werden. Dem einfachen Namen der Klasse müsste also der
Paketname p1
, gefolgt von einem Punkt, vorangestellt werden.
Um die im Quelltext benötigten Klassen eines Pakets pauschal zu importieren,
kann nach dem Paketnamen und dem obligatorischen Punkt das Zeichen "*" folgen.
Falls lediglich eine einzelne Klasse importiert werden soll, kann das Sternsymbol
durch den entsprechenden Klassennamen ersetzt werden.
In der folgenden Übersicht kann PaketName
angepasst werden, um auch Pakete innerhalb weiterer Pakete zu adressieren.
import PaketName.*;
import PaketName.KlassenName;
Das anschließende Beispiel PackageExample3.java
verwendet zwei
import
-Angaben. Die zuvor in Listing 1.18
und Listing 1.19 definierten Klassen sollen im Beispiel
verwendet werden. Der Quelltext bzw. die zugehörige Klassendatei
PackageExample3.class
befinden sich im gewählten Ausgangsverzeichnis
und die benötigten zwei Klassendeklarationen mit Paketzugehörigkeit sind in
entsprechenden Unterordnern abgespeichert.
Ausgangsverzeichnis: PackageExample3.java
Ausgangsverzeichnis/p1: PackageExample1.java
Ausgangsverzeichnis/p1/p2: PackageExample2.java
Bei der Verwendung von import
ist zu beachten, dass eine
zu importierende Klasse als public
deklariert wurde. Andernfalls
ist die Klasse außerhalb des Pakets nicht zugänglich. Die erste
import
-Angabe des Beispiels macht die Klassen des Pakets p1
zugänglich (das Paket im Beispiel enthält nur eine Klasse). Mit der zweiten
Verwendung des Schlüsselworts import
wird gezielt die Klasse
PackageExample2
im entsprechenden Unterpaket adressiert.
Der Quelltext führt nach dessen Übersetzung und Ausführung zur Ausgabe
"3", "method11", "4" und "method21".
Listing 1.20. PackageExample3.java
. Importieren der Klassen
PackageExample1
und PackageExample2
.
import p1.*;
import p1.p2.PackageExample2;
public class PackageExample3 {
public static void main(String[] args) {
int c1 = PackageExample1.a1;
System.out.println(c1);
PackageExample1.method11();
PackageExample2 pe2 = new PackageExample2();
int c2 = pe2.a2;
System.out.println(c2);
pe2.method21();
}
}
Das Beispiel könnte auch ohne die beiden import
-Angaben
realisiert werden. Ein entsprechendes Äquivalent des Quelltextes könnte dann
so aussehen:
/* PackageExample3.java */
public class PackageExample3 {
public static void main(String[] args) {
int c1 = p1.PackageExample1.a1;
System.out.println(c1);
p1.PackageExample1.method11();
p1.p2.PackageExample2 pe2 = new p1.p2.PackageExample2();
int c2 = pe2.a2;
System.out.println(c2);
pe2.method21();
}
}
Statischer Import
Innerhalb einer Importdeklaration kann auch das Schlüsselwort
static
verwendet werden. Damit können zugängliche statische
Bestandteile einer bestimmten Klasse importiert werden.
import static PaketName.KlassenName.*;
import static PaketName.KlassenName.StatischesMitgliedName;
Das folgende Beispiel macht von dieser Möglichkeit Gebrauch. Im Vergleich
zu Listing 1.20 kann dadurch auf das statische Feld
a1
und die statische Methode method11
direkt
zugegriffen werden.
Listing 1.21. PackageExample4.java
. Importieren der satischen
Bestandteile der Klasse PackageExample1
.
import static p1.PackageExample1.*;
public class PackageExample4 {
public static void main(String[] args) {
int c1 = a1;
System.out.println(c1);
method11();
}
}
Automatischer Import
Innerhalb von Listing 1.20 wurde zweimal
das Schlüsselwort import
verwendet, um ein Paket bzw. eine
einzelne Klasse zu importieren. Es wird aber generell auch ein automatischer
Import des Pakets java.lang
durchgeführt. Das Paket
ist Bestandteil des Java Development Kits (JDK) bzw. der Java-Laufzeitumgebung
(JRE). Es beinhaltet fundamentale Klassen für die Programmerstellung, die sich
in der Archivdatei rt.jar
befinden. Der Import des Pakets
java.lang
wird bei der Erstellung einer Klasse automatisch
durchgeführt und bedarf keiner expliziten import
-Angabe. Die
Klasse System
ist z.B. Bestandteil des Pakets java.lang
.
Die Klasse wurde bei vorhergehenden Beispielen bereits oft verwendet, um mit Hilfe
der Methode println
eine Konsolenausgabe zu erzeugen. Ohne den
beschriebenen automatischen Import wäre die Klasse System
nicht
verfügbar und der Compiler javac
würde dies mit einer Fehlermeldung
anzeigen.