3.5 Pakete und import-Deklarationen nutzen 

Ein Paket ist eine Gruppe thematisch zusammengehöriger Typen. Pakete könnten Unterpakete besitzen, die in der Angabe durch einen Punkt getrennt werden. Die Gruppierung lässt sich sehr gut an der Java-Bibliothek beobachten, wo sich zum Beispiel eine Klasse URL und Socket im Paket java.net befinden, denn URLs und Sockets gehören eben zu Netzwerkdingen. Ein Punkt und ein Polygon, repräsentiert durch die Klassen Point und Polygon, gehören in das Paket für grafische Oberflächen, und das ist das Paket java.awt.
Die Paketnamen java, javax und sun
Sun hat für sich selbst die Hauptpaketnamen java, javax und sun reserviert, unter denen eigene Klassen und Unterpakete nicht liegen sollen. So befindet sich 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.ui, würde er damit Verwirrung schaffen, da nicht mehr nachvollziehbar ist, ob das Paket – wie bei den Sun-Klassen – Bestandteil jeder Distribution ist.
3.5.1 Volle Qualifizierung und import-Deklaration 

Um die Klasse Point, die im Paket java.awt liegt, außerhalb des Pakets java.awt zu nutzen, muss sie dem Compiler mit der gesamten Paketangabe bekannt gemacht werden. Hierzu reicht der Klassenname allein nicht aus, denn es kann ja sein, dass der Klassenname mehrdeutig ist und eine Klassendeklaration in unterschiedlichen Paketen existiert. (In der Java-Bibliothek gibt es dazu einige Beispiele, etwa java.util.Date und java.sql.Date.)
Um dem Compiler die präzise Zuordnung einer Klasse zu einem Paket zu ermöglichen, gibt es zwei Möglichkeiten: Zum einen lassen sich die Typen voll qualifizieren, wie wir das bisher getan haben. Eine alternative und praktischere Möglichkeit besteht darin, den Compiler mit einer import-Deklaration auf die Typen im Paket aufmerksam zu machen.
Listing 3.2 AwtWithoutImport.java class AwtWithoutImport { public static void main(String[] args) { java.awt.Point p=new java.awt.Point(); java.awt.Polygon poly=new java.awt.Polygon(); poly.addPoint( 10, 10 ); poly.addPoint( 10, 20 ); poly.addPoint( 20, 10 ); System.out.println( p ); System.out.println( poly.contains(15, 15) ); } } |
Listing 3.3 AwtWithImport.java import java.awt.Point; import java.awt.Polygon; class AwtWithImport { public static void main(String[] args) { Point p = new Point(); Polygon poly = new Polygon(); poly.addPoint( 10, 10 ); poly.addPoint( 10, 20 ); poly.addPoint( 20, 10 ); System.out.println( p ); System.out.println( poly.contains(15, 15) ); } } |
Während der Quellcode auf der linken Seite die volle Qualifizierung verwendet und jeder Verweis auf einen Typ mehr Schreibarbeit kostet, ist im rechten Fall beim import nur der Klassenname genannt und die Paketangabe in ein import »ausgelagert«. Kommt der Compiler zu einer Anweisung wie Point p = new Point();, findet er die Deklaration einer Klasse Point im Paket java.awt und kennt damit die für ihn unabkömmliche absolute Qualifizierung.
Hinweis Die Typen aus java.lang sind automatisch importiert, sodass zum Beispiel ein import java.lang.String; nicht nötig ist. |
3.5.2 import * 

Greift eine Java-Klasse auf mehrere andere Typen des gleichen Pakets zurück, kann die Anzahl der import-Deklarationen groß werden. In unserem Beispiel sind das mit Point und Polygon nur zwei Klassen aus java.awt, aber es lässt sich schnell ausmalen, was passiert, wenn aus dem Paket für grafische Oberflächen zusätzlich Fenster, Beschriftungen, Schaltflächen, Schieberegel und so weiter eingebunden werden. Die Lösung in diesem Fall ist ein *, welches das letzte Glied in einer import-Deklaration sein darf.
Mit dieser Syntax kennt der Compiler alle Typen im Paket java.awt und java.io, sodass eine Klasse Point und Polygon genau bekannt ist, wie auch die Klasse File.
Hinweis Das * ist nur in der letzten Hierarchie erlaubt und gilt immer für alle Typen in diesem Paket. Syntaktisch falsch sind: |
import *; // Syntax error on token "*", Identifier expected import java.awt.Po*; // Syntax error on token "*", delete this token Eine Anweisung wie import java.*; ist zwar syntaktisch korrekt, aber dennoch ohne Wirkung, denn direkt im Paket java gibt es keine Typendeklarationen, sondern nur Unterpakete. |
Das * verkürzt zwar die Anzahl der individuellen import-Deklarationen, es ist aber gut, zwei Dinge im Kopf zu behalten:
- Falls zwei unterschiedliche Pakete einen gleichlautenden Typ beherbergen, etwa Date in java.util und java.sql, so kommt es bei der Verwendung des Typs zu einem Übersetzungsfehler. Hier muss voll qualifiziert werden.
- Die Anzahl der import-Deklarationen sagt etwas über den Grad der Komplexität aus. Je mehr import-Deklarationen, desto größer die Abhängigkeiten zu anderen Klassen, was im Allgemeinen ein Alarmzeichen ist. Zwar zeigen grafische Tools die Abhängigkeiten genau an, doch ein import * kann diese erst einmal verstecken.