Java, Packages

Packages und Ausnahmen


Packages

Ein Package (Paket) enthält eine oder mehrere Klassen, die sich einen Geltungsbereich (Namespace) für Klassen teilen. Klassennamen brauchen nur innerhalb eines Packages eindeutig zu sein. Dies vermeidet mögliche Namenskonflikte zwischen verschiedenen Klassen, die von der lokalen Festplatte oder über das Netz dynamisch geladen werden.

Um eine Java-Datei einem Paket zuzuordnen, kann man an den Anfang der Datei eine package-Anweisung schreiben.

   package game;

Dies definiert das Package game, das die in der Datei definierten Klassen enthält. Falls die Datei keine package-Anweisung enthält, werden die in der Datei definierten Klassen dem standardmäßigen namenlosen Package zugeordnet.

Wenn man in einer Datei Klassen eines anderen Packages benutzen will, muß man den Klassennamen komplett mit Package-Namen angeben. Will man z.B. die Klasse Date im java.util-Package benutzen, so wird dies wie im unten angeführten Beispiel getan.

   java.util.Date d = new java.util.Date();
   System.out.println("today is: "+d);

Die vollen Packagenamen können weggelassen werden, wenn die import-Anweisung benutzt wird.

   import java.util.Date;
   ...
   Date d = new Date();
   System.out.println("today is: "+d);

Man kann auch mit * alle Klassennamen eines Packages oder alle Methoden und Variablen einer Klasse importieren.

   import java.util.*;
   ...
   Date d = new Date();
   System.out.println("today is: "+d);
   ...
   Vector v = new Vector();
   v.addElement("hello");
   v.addElement("bye");

Das Package java.lang enthält die Basisklassen für Java und wird immer importiert. Deswegen kann man z.B. Object, System, Integer usw. ohne ihren Package-Namen java.lang benutzen.

Umfang der JDKs

Das Java-API (Application Programming Interface) (JDK-1.0) besteht aus den Klassen, die in den folgenden acht Packages definiert sind:

   java.applet
   java.awt
   java.awt.image
   java.awt.peer
   java.io
   java.lang
   java.net
   java.util

Bei dem Java-1.1-API (JDK-1.1) haben sich die genannten Packages leicht geändert und es sind die folgenden Packages hinzu gekommen:

   java.beans     Komponenten
   java.event
   java.math
   java.rmi
   java.sql
   java.text
   java.util.zip

Bei dem Java-2-API (JDK-1.2) kommen neben vielen Erweiterungen und Verbesserungen vorhandener Pakete, unter anderem folgende Pakete hinzu:

   java.security
   java.awt.swing
   java.awt.accessability
   java.lang.ref      interact with CG 
   java.lang.reflect
   java.util.jar
   javax.swing
   javax.servlet
   org.omg.CORBA

Bei dem Java-2-API (JDK-1.3) kommen neben Erweiterungen zum JDK-1.2 und Verbesserungen vorhandener Pakete, unter anderem folgende Pakete hinzu:

   java.geom          2D Grafik 
   javax.naming       JNDI 
   javax.sound
   org.omg.CORBA_2_3

Bei dem Java-2-API (JDK-1.4) kommen neben Erweiterungen zum JDK-1.3 und Verbesserungen vorhandener Pakete, unter anderem folgende Pakete hinzu:

   java.nio           new I/O
   javax.xml          XML
   org.w3c            W3C DOM
   org.xml            SAX
   org.ietf.jgss      security
   javax.net.ssl
   javax.imageio 

Bei dem Java-2-API (JDK-1.5) kommen neben Erweiterungen zum JDK-1.4 und Verbesserungen vorhandener Pakete, unter anderem folgende Pakete hinzu:

   java.lang.annotation Unterstüzung für Code-Annotationen
   java.swing           neue Themes
   java.util.concurrent neue Multi-Threading Erweiterungen

   javax.rmi.ssl        SSL für RMI
   javax.security.sasl  SASL Unterstützung
   javax.sql.rowset     Ergebnis Bearbeitung in JDBC
   javax.sound          mehr Soundtreiber

   com.sun.jmx          management extensions
   com.sun.org.apache   XML und HTTP Erweitrungen
                        war zT in org.apache 
   com.sun.corba        aktuelle CORBA Version und Erweiterungen

Weiter wurde die Java Sprache in 1.5 wesentlich erweitert (siehe auch Abschnitt Generics).

Code-Umfang der JDKs

Abbildung: Lines-of-Code der JDKs
was \ JDK Version 1.0.2 1.1.8 1.2.2 1.3.1 1.4.0 1.5.0
lines of Java code 36.080 152.347 502.726 574.034 1.183.279 1.872.648
words in Java code 156.799 707.193 2.085.638 2.373.953 4.718.321 7.534.701
bytes in src-dir 1.0 MB 7.0 MB 20.0 MB 24.0 MB 48.0 MB 77.9 MB
public class or interface 122 736 1.649 1.952 3.993 6.517
directories / packages 14 35 88 98 238 430
@authors, see 1 21 114 100 236 315 529
if ( ) 1.319 4.648 18.209 23.190 44.006 68.125
for ( ) 236 1.692 2.727 5.065 10.031 7.893
while ( ) 105 269 985 1.134 1.625 3.249
switch ( ) 33 107 410 465 839 1.308
try { } 93 112 507 602 2.143 5.402
catch ( ) 108 307 909 1.126 3.505 6.038
throw new 167 709 2.011 2.294 6.700 9.590
boolean 322 1.029 4.286 4.818 9.532 15.233
int 1.556 5.043 19.613 21.599 41.679 62.054
long 130 810 754 1.890 3.250 5.315
float 43 104 1.030 1.134 1.625 1.885
double 71 181 1.057 1.427 1.862 2.169
public 1.976 5.828 21.110 24.368 50.209 85.553
private 303 1.948 5.120 6.477 13.900 22.943
protected 151 689 3.695 4.201 6.399 9.626
abstract class 17 74 214 319 545 736
/** comments */, see 2 2.268 6.503 22.443 25.492 49.592 73.036

Bemerkungen:

  1. ohne Namen zu normalisieren und nur die genannten
  2. d.h. öffentliche mit javadoc dokumentierte Objekte

Die Zahlen wurden im wesentlichen mit grep pattern cat.java|wc ermittelt. Die Datei cat.java wurde mit find src-dir -name "*.java" |xargs cat > cat.java erzeugt.

Daneben gibt es in den jeweiligen JDKs noch viele class-Dateien ohne java-Dateien, wo also der Source-Code nicht bekannt ist.


Zugriff und Sichtbarkeit

Eine als public deklarierte Klasse ist in allen Packages zugreifbar. Auf eine nicht als public deklarierte Klasse kann nur innerhalb desselben Package zugegriffen werden.

Zur Verdeutlichung der Konzepte betrachten wir folgende Beispiele:

  public class A {
    public       int pub;
    protected    int pro;
    private      int piv;
    /*default*/  int def; // = package private
                             /* 0 */
  }

  public class B extends A {
    A a = new A();           /* 1 */
  }

  public class C {
    A a = new A();           /* 2 */
  }

An der Stelle /* 0 */ kann auf alle Variablen zugegriffen werden.

An der Stelle /* 1 */ gilt folgendes:

An der Stelle /* 2 */ gilt:


Abbildung 1.2: Java-Sichtbarkeit
Sichtbarkeit public protected default package private
Klasse/Objekt
definierende Klasse ja ja ja ja
gleiches Package ja ja ja nein
anderes Package ja nein nein nein
Vererbung
gleiches Package ja ja ja nein
anderes Package ja ja nein nein

Auf public-Felder (Variablen oder Methoden) kann in allen Packages und Subklassen zugegriffen werden, solange die Klasse selbst zugreifbar ist. Auf protected-Felder kann in Subklassen der Klasse und in allen Klassen im gleichen Package zugegriffen werden. private-Felder sind dagegen nur in derselben Klasse zugreifbar. Diese Beziehungen sind nochmal in Abbildung 1.2 zusammengefaßt.

Konstanten

Konstante Variablen können mit dem Schlüsselwort final deklariert werden. Diese können dann nicht mehr geändert werden.

   public final static String DEFAULT = "dpunkt";

Im Gegensatz zu C oder C++ gibt es keinen Preprozessor, der Konstanten substituieren kann (z.B. kein #define).

Final-Klassen

Von Klassen, die mit dem Schlüsselwort final deklariert sind, können keine Klassen abgeleitet werden. Dies dient zum einen dazu, unerwünschte Ableitungen zu verhindern, wie zum Beispiel bei system-nahen Klassen java.lang.System. Und sie dienen zum anderen dazu, dem Compiler Hinweise für die Optimierung zugeben, denn es müssen dann keine Vorkehrungen zum Überschreiben dieser Methoden getroffen werden.

Ausnahmebehandlung

Ein Ausnahmefehler (Exception) ist ein Signal, das irgendeinen Fehler andeutet. Man kann eine Exception durch throw auslösen und durch catch abfangen. Ein neues Exception-Objekt wird wie üblich mit new erzeugt.

Java unterscheidet im Wesentlichen drei Arten von Ausnahmen, die alle von der Klasse java.lang.Throwable abgeleitet sind:

Exception:
Für eine Anwendung wichtige Informationen, die für die weitere Verarbeitung entsprechend behandelt werden sollte. Der Compiler achtet darauf, dass Exceptions behandelt oder weitergereicht werden.
RuntimeException
Ebenfalls wichtige Information, die bei Bedarf der Anwendung behandelt werden kann oder zum Abbruch der Anwendung führen sollte. Sie werden vom Compiler nicht explizit beachtet.
Error
Unvorhergesehener Fehler, der in der Regel zum Abbruch der Anwendung führen sollte. Sie werden vom Compiler nicht explizit beachtet.

Falls eine Exception nicht in der Methode abgefangen wird, wird sie in die Methode weitergeleitet, die diese Methode aufgerufen hat. Dies ermöglicht bessere und einfachere Fehlerbehandlung. Jede Methode in Java muß Exceptions entweder explizit abfangen oder weiterleiten. Zum Abfangen kann man try und catch wie folgt benutzen.

   try {
       // open a file
       ...
       // read data
       ...
   } catch (IOException e) {
           System.out.println("Couldn't write");
           // do the clean up, e.g. closing the file
           e.printStackTrace();
   }

Die vollständige Syntax dieser Anweisungsfolge ist:

   try {
            // statements possibly generating
            // Exception_1 or Exception_2
   } catch (Exception_1 e) {
            // statements handling Exception_1
   } catch (Exception_2 e) {
            // statements handling Exception_2
   ...
   } finally {
            // statements cleaning up for all the cases
   }
Der finally-Block wird unabhängig vom Auftreten von Ausnahmen zum Schluß ausgeführt.

Zum Weiterleiten von Ausnahmen kann man das throws-Schlüsselwort benutzen. throws wird zwischen dem Methodenkopf und dem Methodenrumpf zusammen mit einer Aufzählung aller in Frage kommenden Ausnahmen eingefügt. Zum Auslösen von Ausnahmen verwendet man das throw-Schlüsselwort.

   public void getInputData() throws MyException {
      ...
      if ( notOK ) { throw new MyException(); }
      ...
   }

Zur Definition einer Ausnahme wird eine Subklasse von java.lang.Exception gebildet.

   class MyException extends Exception {
 
      public MyException() { ...; }
      public MyException(String msg) { ...; }

   }

java.lang.Exception ist eine direkte Subklasse von java.lang.Throwable:

public class Exception 
       extends Throwable
       implements Serializable

   Exception()
   Exception(String message)
   Exception(String message, Throwable cause)
   Exception(Throwable cause) 

   Throwable getCause()
   Throwable initCause(Throwable cause)

   String getMessage()
   void printStackTrace()

Beispiele:

public class Ausnahmen { 
 
  public void exception() throws NumberFormatException { 
    int n = 0; 
                      
    try { 
            // versuche irgendwelche Methodenaufrufe, die  
            // Ausnahmen produzieren koennen 
    } catch (IndexOutOfBoundsException e1) { 
            // Fehlerbehandlung 
            // meist Ausgabe einer Fehlermeldung 
            // das Programm arbeitet dann weiter 
            // nach dem letzten catch-Block 
    } catch (Exception e2) { 
            // hier werden alle Ausnahmen abgefangen  
            // die nicht schon vorher behandelt 
            // wurden 
    } finally { 
            // dieser Block ist optional, er wird nach  
            // jedem Verlassen des try-Blocks ausgefuehrt 
    } 
                      
    if ( n < 0 ) { 
       throw new NumberFormatException("Die Variable n enthaelt"+ 
                                       " einen Wert kleiner als 0!"); 
    }
  } 
} 

© Universität Mannheim, Rechenzentrum, 1998-2005.

Heinz Kredel
Last modified: Mon Jan 23 22:53:54 CET 2006