Packages
Ziele
- Ich kann ohne Hilfsmittel mindestens zwei Vorteile für das Verwenden von Packages nennen.
- Ich kann ohne Hilfsmittel die Namenkonvention für Java-Packages beschreiben.
- Ich zeige auf, wie mehrere Klassen vom gleichen Packet mit einem
import
-Statement importiert werden. - Ich kann korrekt und ohne Hilfsmittel erklären, was ein statischer Import ist und wozu er verwendet wird.
- Ich kann erläutern, warum es keine gute Idee ist, Klassen ohne Package-Anweisung zu schreiben.
Packages
Bevor wir uns intensiver mit den Bestandteilen einer Klasse auseinandersetzen, schauen wir uns Packages an. Ein Package dient der Gruppierung und Organisation von Klassen, Schnittstellen und anderen Packages. Es wird zwischen zwei Arten von Packages unterschieden:
- implizit importierte Packages
- explizit zu importierende Packages
Wenn wir beispielsweise die Klasse Scanner benötigen, müssen wir dies durch ein import Statement machen.
|
|
Die Klasse Scanner befindet sich also im Package java und darin im Package util. Ein Package kann beliebig viele andere Packages enthalten. Ein Package wird auf dem Dateisystem als Verzeichnis behandelt.
Vorteile
- Code-Organisation. Klassen von gleicher Natur (wie beispielsweise Modelle oder Services) befinden sich im gleichen Package
- Auffindbarkeit. Klassen sind durch die Organisation einfacher zu finden
- Vermeiden von Namenskonflikten. Zwei Klassen dürfen den gleichen Namen haben, solange sie in unterschiedlichen Packages liegen
- Zugriffsteuerung. Bestimmte Zugriffsmodifikatoren erlauben den Zugriff auf Klassen im gleichen Package
Namenskonventionen
Gemäss der Namenskonvention werden Package-Namen immer in Kleinbuchstaben geschrieben. Die Trennung der verschiedenen Packages erfolgt beim Import-Statement durch einen Punkt.
Ordnerstruktur
Programmcode muss organisiert sein. Obwohl die Ordnerstruktur nicht vorgegeben ist, hat sich die folgende Konvention in Java-Projekten (vor allem solche, welche Maven im Einsatz haben - dazu mehr im Maven-Modul) etabliert.
Grundsätzlich legen wir Quellcode im einem Verzeichnis ab, das src genannt wird. Innerhalb dieses Verzeichnisses legen wir ein Verzeichnis main und darin wiederum ein Verzeichnis java an. Innerhalb des Java-Verzeichnisses können wir beliebig viele eigene Packages anlegen, um unseren Programmcode zu organisieren.
Klassen mit gleichem Namen
Es kann passieren, dass wir zwei Klassen haben, die den gleichen Namen haben. Beispiel: Wir arbeiten mit der externen Bibliothek Abstract Window Toolkit (AWT). Darin gibt es eine Klasse mit dem Namen Rectangle. Es ist natürlich erlaubt eine eigene Klasse mit diesem Namen anzulegen, solang sie sich nicht in einem Package mit dem gleichen Namen befindet.
|
|
- Wir importieren die eigene Rectangle-Klasse mit der Import-Anweisung
- Wir deklarieren und initialisieren ein AWT-Rectangle, indem wir den vollständigen Namen (Package und Klassennamen) angeben
Import *
Wenn sich zwei Klassen im selben Paket befinden und eine Klasse in der anderen verwendet wird, muss die Klasse nicht importiert werden.
Es ist auch möglich, alle Klassen aus dem Paket zu importieren. Dazu müssen wir einen *
anstelle eines bestimmten Klassennamens in das Import-Statement schreiben.
|
|
Alle Klassen eines Packages, wie in diesem Beispiel, zu importieren ist schlechter Style und soll vermieden werden. Es soll immer explizit importiert werden.
Package java.lang
Obwohl wir die meisten Pakete importieren müssen, gibt es ein Java-Paket, das immer automatisch importiert wird. Es ist java.lang
. Dieses Paket enthält viele weit verbreitete Klassen wie String
, System
, Long
, Integer
, NullPointerException
und andere.
Statischer Import
Wir können auch statische Elemente (wie z.B. Konstanten oder auch statische Methoden) einer Klasse in eine andere Klasse importieren. Wenn wir *
in die import-Anweisung schreiben, müssen wir den importierten Klassennamen nicht angeben, bevor wir statische Methoden aufrufen oder statische Felder lesen.
Hier ist ein Beispiel für den statischen Import der Klasse Arrays
, die viele nützliche Methoden zur Verarbeitung von Arrays enthält:
|
|
Wenn wir bei der Implementation von Klassen keine Package-Anweisung schreiben, wird die Klasse ins Default-Package eingefügt. Dies sollte vermieden werden, da Klassen aus dem Default-Package nicht in andere Klasse importiert werden können, welche sich nicht auch im Default-Package befinden.
Eigene Packages definieren
Packages können auch selber definiert werden. Die Package-Struktur entspricht hierbei der Verzeichnisstruktur des Projekts. Packages erstellt man primär um den Code zu strukturieren.
In einem Spring Boot Projekt wird der Code typischerweise in folgende Packages unterteilt:
- Controller-Package (ch.sbb.demo.controller): Beinhaltet die Controller-Klassen, die HTTP-Anfragen verarbeiten.
- Service-Package (ch.sbb.demo.service): Enthält die Service-Klassen, die die Geschäftslogik implementieren.
- Repository-Package (ch.sbb.demo.repository): Beinhaltet die Repository-Klassen für die Datenbankinteraktionen
- Model-Package (ch.sbb.demo.model): Enthält die Datenmodellklassen (Entities), die die Datenbanktabellen repräsentieren.
Ein eigene Package-Struktur zu definieren ist also gar nicht so schwer, im Grunde muss man dafür nur Verzeichnise erstellen.
Wie der Import von eigen definierten Packages erfolgt, ist dem folgenden Beispiel zu entnehmen. Im Beispiel gehen wir von dieser Verzeichnisstruktur aus:
|
|
Die Ordner ch
, sbb
examplepackage
wurden von Hand erstellt.
Das Package enthält die Klasse Beispiel.java
.
|
|
In einer anderen Klasse kann das Package wie zuvor beschrieben importiert und verwendet werden. Ein Beispiel für eine Klasse welche das Package importiert und verwendet könnte wie folgt aussehen:
|
|