Kurzinformationen zur Programmiersprache Java

Das erste Java-Programm

  • Legen Sie in dem Verzeichnis, in dem Sie Ihre Java-Klassen ablegen wollen, ein neues Verzeichnis an.
  • Erstellen Sie mit einem Editor Ihres Systems eine Datei namens Start.java, die folgenden Inhalt hat:

public class Start { public static void main(String[] argv) { System.out.println(“That’s one small step for man, one giant leap for mankind.”); } }

  • Erzeugen Sie mit dem Java-Übersetzer javac aus dem eben erstellten Programmtext eine .class-Datei: javac Start.java
  • Jede .class-Datei, deren zugehörige Klasse eine main-Methode enthält, kann mit der virtuellen Maschine von Java ausgeführt werden: Geben Sie den Befehl java Start ein (Hinweis: beim Starten wird die Dateiendung .class weggelassen). Der Code des eben beschriebenen Programms wird jetzt ausgeführt.
  • Sollte es bei einem der beiden Schritte Probleme geben, müssen Sie der Umgebungsvariablen CLASSPATH das aktuelle Verzeichnis zufügen, entweder durch explizites Angeben des Verzeichnisses oder durch Zufügen von “.” (Punkt), was stets das gerade aktuelle Verzeichnis bezeichnet.

Der Java CLASSPATH

von Philipp Becker

Was ist der CLASSPATH und wofür braucht man ihn?

Beim Programmieren mit Java kommt man früher oder später (meist sehr viel früher) an den Punkt, an dem man sich eigene Klassen schreibt und diese in anderen Klassen einsetzt. Zum Beispiel könnten in einer Klasse “Strassenkarte” Objekte der Klassen “Autobahn” und “Stadt” verwendet werden.

Doch damit das überhaupt möglich ist, müssen sowohl der Compiler (javac) als auch die Laufzeitumgebung (java) wissen, wo sie die zugehörigen .class-Dateien suchen müssen (in diesem Fall “Stadt.class” und “Autobahn.class”). An dieser Stelle kommt der CLASSPATH ins Spiel.

Der CLASSPATH ist eine Auflistung aller Pfade, in denen bei Bedarf nach den benötigten Klassen gesucht werden soll. Standardmäßig ist im CLASSPATH nur das aktuelle Verzeichniss enthalten, in dem man sich gerade befindet (“.”). Daher können in unserem Beispiel die Klassen “Autobahn” und “Stadt” einfach verwendet werden, wenn deren zughörige .class-Dateien im gleichen Verzeichniss liegen wie die Klasse “Strassenkarte”.

Will man aber außerdem noch eigene Klassen benutzen, die sich zum Beispiel in dem Verzeichniss “~/Klassen” (das ist das Unterverzeichnis “Klassen” im eigenen Home-Verzeichnis) befinden, so muss man den CLASSPATH um diesen Verzeichnissnamen erweitern, damit die Klassen auch gefunden werden.

Wie hängen der CLASSPATH und die “import”-Anweisung zusammen?

Mit der “import”-Anweisung lassen sich Klassen benutzen, die zu Packages gehören. Man könnte zum Beispiel die Klasse “Autobahn” so definieren, dass sie zum Package “karte.verbindung” gehört. Das bedeutet, dass die Datei “Autobahn.java” auch im Verzeichnis “karte/verbindung/” abgelegt wird.

Um ab diesem Punkt das Beispiel noch etwas konkreter zu machen: Unsere Klasse “Autobahn” (die zum Package “karte.verbindung” gehört) liegt im Verzeichnis “/Beispiel/karte/verbindung/“. Wir selber befinden uns im Moment im Verzeichnis”/Beispiel/” und wollen dort eine Datei “test.java” kompilieren, die die Klasse “Autobahn” nutzt. Damit das funktioniert, muss in “test.java” ein Anweisung “import karte.verbindung.Autobahn” vorhanden sein (oder auch “import karte.verbindung.*“, wenn wir auf alle Klassen dieses Packages zugreifen können wollen). Desweiteren muss im CLASSPATH das Verzeichnis”~/Beispiel" eingetragen sein (“.” reicht auch, falls wir uns schon in diesem Verzeichnis befinden – “.” ist aber schon standardmäßig im CLASSPATH enthalten, in diesem Fall brauchen wir also gar nichts zu tun). Das Verzeichnis “~/Beispiel/karte/verbindung” hingegen wird nicht in den CLASSPATH eingetragen. Durch die “import”-Anweisung wissen java und javac bereits, dass sie in den Verzeichnissen des CLASSPATH nach passenden Unterverzeichnissen und dort nach den passenden Klassen suchen sollen.

Hinweis: Manchmal sind Packages auch in .jar-Dateien zusammengefasst. Wenn man ein Package nutzen will, das sich in einer .jar-Datei befindet, muss man diese Datei in den CLASSPATH mit aufnehmen (die Datei selber, nicht nur das Verzeichnis, in dem sie liegt).

Wie sehe ich, welcher CLASSPATH bei mir bereits gesetzt ist?

Auf den Rechnern des SCI bzw. unter typischen Unix-Umgebungen geschieht dies über folgenden Befehl: ich@tux1[~] echo $CLASSPATH

Erhält man als Ergebnis eine Meldung ähnlich folgender CLASSPATH: Undefined variable.

dann bedeutet dies, dass kein CLASSPATH gesetzt ist. Damit gilt automatisch der Standard-Classpath von “.” (das aktuelle Verzeichnis, siehe oben). Das selbe gilt, falls man nur eine leere Zeile als Ausgabe erhält.

Bekommt man beispielsweise die folgende Ausgabe:

ich@tux1[~] echo $CLASSPATH /edu1/essy1h02:. bedeutet dies, dass momentan zwei Verzeichnisse im CLASSPATH enthalten sind (getrennt durch “:”): das Verzeichnis “/edu1/essy1h02” und das Verzeichnis “.” (aktuelles Verzeichnis).

Wie setzt man den CLASSPATH?

Hier hat man zwei Möglichkeiten:

  • Zum einen gibt es die Möglichkeit, den Programmen den zu verwendenden CLASSPATH beim Programm-Aufruf zu übergeben. Dafür existiert der Kommandozeilenparameter “-classpath”, der eine Liste der zu verwendeten Verzeichnisse enthält. Die Verzeichnisse werden dabei per “:” voneinander getrennt.

    Beispiele: ich@tux1[~] javac -classpath .:~/Klassen test.java ich@tux1[~] java -classpath .:~/Klassen test

  • Die andere Möglichkeit besteht darin, die Umgebungsvariable $CLASSPATH zu setzen. Im SCI ist standardmäßig die tcsh als shell eingestellt (wer jetzt nicht weiß, was das bedeutet: macht nix ;-)); dort kann man den CLASSPATH folgendermaßen setzen: ich@tux1[~] setenv CLASSPATH .:~/Klassen:/edu1/test

    Hier wurden jetzt die drei Verzeichnisse “.”, “~/Klassen” und “/edu1/test” als CLASSPATH festgelegt.

    Benutzt man als shell die bash, lautet der gleiche Befehl wie folgt: ich@tux1[~] export CLASSPATH=.:~/Klassen:/edu1/test

Sobald man die Standardvariable $CLASSPATH gesetzt hat, benutzen Programme wie java, javac, javadoc automatisch den dort eingestellen CLASSPATH.

Ausnahme: Wenn beim Aufruf von javac, java, javadoc, etc. auf der Kommandozeile ein anderer CLASSPATH mit angegeben wird, so wird der Inhalt der $CLASSPATH-Variable während dieses Aufrufs ignoriert.

Warum kann ich z.B. die Klassen String, !ArrayList, !BufferedReader etc. benutzen, ohne dass die zugehörigen Verzeichnisse in meinem CLASSPATH auftauchen?

Diese Klassen gehören zur Standard-Installation des SDK (Software Development Kit, d.h. der Java-Compiler “javac”, die Java Virtual Machine “java”, das javadoc-Programm und noch weitere Tools) dazu und werden automatisch gefunden und benutzt. Daher müssen sie auch nicht im CLASSPATH enthalten sein.

In welcher Reihenfolge werden Klassen gesucht?

Zuerst werden die im SDK enthaltenen Klassen durchsucht und erst danach die im CLASSPATH enthaltenen Verzeichnisse in der Reihenfolge, in der sie auch im CLASSPATH auftauchen. Es ist also nicht möglich, z.B. die Klasse “String” durch eine eigene Klasse gleichen Namens zu ersetzen.

Welche Probleme können bei der Benutzung des CLASSPATH auftreten?

Des öfteren wird beim Setzen des CLASSPATH vergessen, das aktuelle Verzeichnis mit aufzunehmen.

Außerdem kann es zu Problemen kommen, falls sich in den im CLASSPATH stehenden Verzeichnissen zwei verschiedene Klassen mit gleichem Namen befinden. In diesem Fall wird die Klasse benutzt, welche von dem Programm zuerst gefunden wird (siehe auch “In welcher Reihenfolge werden Klassen gesucht”), egal, ob dies nun die richtige ist oder nicht.

(Wie) Kann man den CLASSPATH dauerhaft setzen?

Wenn man den CLASSPATH wirklich dauerhaft setzen will, muss man die Datei ~/.cshrc editieren. Gelegentlich ist bereits eine Zeile vorhanden, die die $CLASSPATH-Umgebungsvariable setzt. Diese kann man an die eigenen Bedürfnisse anpassen (siehe: Wie setzt man den CLASSPATH).