Getrennte Übersetzung in Java
Ein Programm kann mehrere Klassen verwenden, die in verschiedenen Übersetzungseinheiten enthalten sind. Eine Übersetzungseinheit kann immer nur ganze Klassen enthalten und beispielsweise keine einzelnen Methodendeklarationen.
An Klassen, die in einer anderen Übersetzungseinheit deklariert werden, lassen sich leicht Nachrichten schicken.
So kann man beispielsweise eine Übersetzungseinheit "Kuckuck.java" mit der Deklaration der Klasse "Kuckuck" erstellen und eine Übersetzungseinheit "Hochzeit.java" mit der Deklaration der Klasse "Hochzeit" anlegen. Aus der Methode "main" einer dritten Klasse "Liedtest" lassen sich dann die Methoden dieser ersten beiden Klassen aufrufen, auch wenn sie in anderen Übersetzungseinheiten deklariert sind.
Kuckuck.java
/** Das Lied "Auf einem Baum ein Kuckuck sass" */
public final class Kuckuck
{ /** Den Refrain des Liedes ausgeben. */
private static void refrainAusgeben()
{ java.lang.System.out.println( "Sim sa la dim, bam ba," );
java.lang.System.out.println( "Sa la du, sa la dim -" ); }
/** Den Text des Liedes ausgeben. */
public static void ausgeben()
{ { java.lang.System.out.println( "Auf einem Baum ein Kuckuck, -" );
refrainAusgeben();
java.lang.System.out.println( "Auf einem Baum ein Kuckuck sass." ); }
{ java.lang.System.out.println( "Da kam ein junger Jaeger, -" );
refrainAusgeben();
java.lang.System.out.println( "Da kam ein junger Jaegersmann." ); }
{ java.lang.System.out.println( "Der schoss den armen Kuckuck, -" );
refrainAusgeben();
java.lang.System.out.println( "Der schoss den armen Kuckuck tot." ); }}}Hochzeit.java
/** Das Lied "Ein Vogel wollte Hochzeit machen" */
public final class Hochzeit
{ /** Den Refrain des Liedes ausgeben. */
private static void refrainAusgeben()
{ java.lang.System.out.println( "Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la!" ); }
/** Den Text des Liedes ausgeben. */
public static void ausgeben()
{ java.lang.System.out.println( "Ein Vogel wollte Hochzeit machen, in dem gruenen Walde." );
refrainAusgeben();
java.lang.System.out.println( "Die Drossel war der Braeutigam, die Amsel war die Braute." );
refrainAusgeben();
java.lang.System.out.println( "Die Lerche, die Lerche, die fuehrt die Braut zur Kerche." );
refrainAusgeben(); }}Liedtest2.java
/** Testklient fuer Liedklassen */
public final class Liedtest2
{ /** Testklient fuer Liedklassen */
public static void main( final java.lang.String[] args )
{ Kuckuck.ausgeben();
Hochzeit.ausgeben(); }}
Es reicht, den Übersetzer mit "javac Liedtest2.java" aufzurufen und die erhaltene Klasse mit "java Liedtest2" auszuführen. Die anderen verwendete Klassen werden dabei nötigenfalls automatisch übersetzt und in das Programm eingebunden.
Die automatische Übersetzung nach Bedarf funktioniert aber nur für eine Klasse, die auch in einer Übersetzungseinheit enthalten ist, die nach dieser Klasse benannt wurde, da der Übersetzer "javac" sonst die Klassendeklaration nicht finden kann. Aus Übersetzungseinheiten mit mehreren Klassendeklarationen müßten dann zuvor durch einen ausdrücklichen Aufruf des Übersetzers "javac" die verschiedenen Klassendateien erzeugt werden. Damit Klassen leicht zu finden sind, ist es empfehlenswert, nur eine Klasse pro Übersetzungseinheit zu deklarieren und die Datei mit der Übersetzungseinheit nach dieser Klasse zu benennen. (Ausgenommen von dieser Regel ist die Möglichkeit, innerhalb einer Klasse weitere „Innenklassen“ zu deklarieren, derer es dann mehrere in einer Übersetzungseinheit geben darf.)
Der Übersetzer erzeugt aus einer Übersetzungseinheit eine Klassendatei, welche die Klassendeklaration in einer Form enthält, die von der Javamaschine direkt verarbeitet werden kann. Wenn die Javamaschine diese Klassendatei lädt, bemerkt sie die Bezüge auf Deklarationen in anderen Klassendateien, sucht diese Klassendateien im selben Verzeichnis, lädt sie und verbindet sie mit der auszuführenden Klassen zu einem vollständigen Programm. Insofern ist bei der Herstellung von Javaprogrammen kein separater Vorgang zum „Verbinden“ der Klassendateien nötig: Diese Vorgang wird von der Javamaschine miterledigt.
Falls keine Klassendatei, aber eine Quelldatei mit dem passenden Namen vorhanden ist, wird bei Bedarf sogar zunächst der Übersetzer gestartet, um die Klassendatei zu erzeugen. Falls eine Quelldatei einer benötigten Klassendatei geändert wurde, ist die Klassendatei veraltet. Dann wird eine eventuell schon vorhandene Klassendatei ignoriert und die Quelldatei automatisch erneut übersetzt, um zunächst eine aktuelle Version der Klassendatei herzustellen und diese dann zu verwenden.
In jeder Übersetzungseinheit sollte nur eine Klasse deklariert werden. Die Übersetzungseinheit sollte den Namen dieser Klasse mit der Erweiterung ".java" haben.
- Beispiel ausführen
- Starten Sie das oben beschriebene Programm "Liedtest2.java" wie oben beschrieben.
- Übersetzungseinheit refaktorieren
- Zerlegen Sie die Lösung einer früheren Übungsaufgabe, bei der mehrere Klassen in einer Übersetzungseinheit deklariert wurden (Ausgabe einer Begrüßung in verschiedenen Sprachen), in mehrere Übersetzungseinheiten, so daß jede Übersetzungseinheit nur eine Klasse enthält, und testen Sie die erzeugten Klassen.
- Math
- Erstellen Sie eine Übersetzungseinheit "Math.java" mit einer beliebigen Klassendeklaration. Versuchen Sie dann in einer weiteren Übersetzungseinheit im selben Verzeichnis die Nachricht "random()" an die Standardklasse "Math" zu schicken, um eine Pseudozufallszahl zu berechnen. Treten dabei Probleme auf und wie lassen diese sich gegebenenfalls lösen, ohne die Übersetzungseinheit "Math.java" zu verändern (ohne sie zu löschen, umzubenennen oder zu verschieben)?