1.8 Das erste Programm compilieren und testen
Nachdem wir die grundlegenden Konzepte von Java besprochen haben, wollen wir ganz dem Zitat von Dennis M. Ritchie folgen, der sagt:
»Eine neue Programmiersprache lernt man nur, wenn man in ihr Programme schreibt.«
In diesem Abschnitt nutzen wir den Java-Compiler und Interpreter von der Kommandozeile. Wer gleich eine ordentliche Entwicklungsumgebung wünscht, der kann problemlos diesen Teil überspringen und bei den IDEs fortfahren. Die Beispiele im Buch basieren auf Windows.
Der Quellcode eines Java-Programms lässt sich so allein nicht ausführen. Ein spezielles Programm, der Compiler (auch Übersetzer genannt), transformiert das geschriebene Programm in eine andere Repräsentation. Im Fall von Java erzeugt der Compiler die DNA jedes Programms, den Bytecode.
1.8.1 Ein Quadratzahlen-Programm
Das erste Java-Programm soll einen Algorithmus ausführen, der die Quadrate (engl. squares) der Zahlen von 1 bis 4 ausgibt. Wir setzen den Quellcode (engl. source code) beispielhaft in das Verzeichnis C:\firstlove. Der Name der Quellcodedatei ist Squares.java. Da der Quellcode reiner Text ist, kann er mit jedem Texteditor angelegt und editiert werden.
Hinweis für Windows-Nutzer: Unter Windows findet sich der Editor Notepad unter Start • Programme • Zubehör • Editor. Beim Abspeichern mit Notepad mithilfe von Datei • Speichern unter… muss bei Dateiname Squares.java stehen und beim Dateityp Alle Dateien ausgewählt sein, damit der Editor nicht automatisch die Dateiendung .txt vergibt.
/**
* Erstes Java-Beispielprogramm.
* @version 1.02 26 Dez 2013
* @author Christian Ullenboom
*/
public class Squares {
static int quadrat( int n ) {
return n * n;
}
static void ausgabe( int n ) {
for ( int i = 1; i <= n; i = i + 1 ) {
String s = "Quadrat(" + i + ") = " + quadrat( i );
System.out.println( s );
}
}
public static void main( String[] args ) {
ausgabe( 4 );
}
}
Die ganze Programmlogik sitzt in einer Klasse Squares, die drei Methoden enthält. Alle Methoden in einer objektorientierten Programmiersprache wie Java müssen in Klassen platziert werden. Die erste Methode, quadrat(int), bekommt als Übergabeparameter eine ganze Zahl und berechnet daraus die Quadratzahl, die sie anschließend zurückgibt. Eine weitere Methode ausgabe(int) übernimmt die Ausgabe der Quadratzahlen bis zu einer vorgegebenen Grenze. Die ausgabe-Methode bedient sich dabei der Methode quadrat(int). Zum Schluss muss es noch ein besonderes Unterprogramm main(String[]) geben, das für den Java-Interpreter den Einstiegspunkt bietet. Die Methode main(String[]) ruft dann die Methode ausgabe(int) auf.
1.8.2 Der Compilerlauf
Wir wechseln zur Eingabeaufforderung (Konsole) und in das Verzeichnis mit dem Quellcode. Liegt die Quellcodedatei vor, übersetzt der Compiler sie in Bytecode. Für unsere Java-Klasse in der Datei Squares.java heißt das:
C:\firstlove>javac Squares.java
Der Compiler legt nun – vorausgesetzt, das Programm war fehlerfrei – die Datei Squares.class an. Diese enthält den Bytecode.
Bei Aufruf von javac muss die zu übersetzende Datei komplett mit Dateiendung angeben werden. Doch auch Wildcards sind möglich: So übersetzt javac *.java alle Java-Klassen im aktuellen Verzeichnis.
Die Beachtung der Groß- und Kleinschreibung ist zwar unter Windows nicht wichtig, doch sollte sie eingehalten werden.
Compilerfehler
Findet der Compiler in einer Zeile einen syntaktischen Fehler, so meldet er diesen unter der Angabe der Datei und der Zeilennummer. Nehmen wir noch einmal unser Quadratzahlen-Programm, und bauen wir in der quadrat(int)-Methode einen Fehler in Zeile 9 ein (das Semikolon fällt der Löschtaste zum Opfer). Der Compilerdurchlauf meldet:
Squares.java:9: ';' expected.
return n * n
^
1 error
Wenn der Compiler aufgrund eines syntaktischen Fehlers eine Übersetzung in Java-Bytecode nicht durchführen kann, sprechen wir von einem Compilerfehler (engl. compile-time error) oder Übersetzungsfehler. Auch wenn der Begriff »Compilerfehler« so klingt, als ob der Compiler selbst einen Fehler hat, ist doch unser Programm fehlerhaft.
1.8.3 Die Laufzeitumgebung
Der vom Compiler erzeugte Bytecode ist kein üblicher Maschinencode für einen speziellen Prozessor, da Java als plattformunabhängige Programmiersprache entworfen wurde, die sich also nicht an einen physikalischen Prozessor klammert – Prozessoren wie Intel-, AMD- oder PowerPC-CPUs können mit diesem Bytecode nichts anfangen. Hier hilft eine Laufzeitumgebung weiter. Diese liest die Bytecode-Datei Anweisung für Anweisung aus und führt sie auf dem konkreten Mikroprozessor aus.
Der Interpreter java bringt das Programm zur Ausführung:
C:\firstlove>java Squares
Quadrat(1) = 1
Quadrat(2) = 4
Quadrat(3) = 9
Quadrat(4) = 16
Als Argument bekommt die Laufzeitumgebung java den Namen der Klasse, die eine main(…)-Methode enthält und somit als ausführbar gilt. Die Angabe ist nicht mit der Endung .class zu versehen, da hier kein Dateiname, sondern ein Klassenname gefordert ist.
[+] Tipp
Ab Java 11 lassen sich sogenannte Single-File Source-Code Programs auch ohne eine Übersetzung durch die Laufzeitumgebung ausführen.[ 45 ](https://openjdk.java.net/jeps/330)
1.8.4 Häufige Compiler- und Interpreter-Probleme
Arbeiten wir auf der Kommandozeilenebene (Shell) ohne integrierte Entwicklungsumgebung, können verschiedene Probleme auftreten. Ist der Pfad zum Compiler nicht richtig gesetzt, gibt der Kommandozeileninterpreter eine Fehlermeldung der Form
$ javac Squares.java
Der Befehl ist entweder falsch geschrieben oder konnte nicht gefunden werden.
Bitte überprüfen Sie die Schreibweise und die Umgebungsvariable 'PATH'.
aus. Unter Unix lautet die Meldung gewohnt kurz:
javac: Command not found
Die Lösung ist hier also, javac in den Suchpfad aufzunehmen, wie wir es vorher schon beschrieben haben.
War der Compilerdurchlauf erfolgreich, können wir den Interpreter mit dem Programm java aufrufen. Verschreiben wir uns bei dem Namen der Klasse oder fügen wir unserem Klassennamen das Suffix .class hinzu, so meckert der Interpreter. Beim Versuch, die nicht existente Klasse Q zum Leben zu erwecken, schreibt der Interpreter auf den Fehlerkanal:
$ java Q
Fehler: Hauptklasse Q konnte nicht gefunden oder geladen werden.
Ursache: java.lang.ClassNotFoundException: Q
Ist der Name der Klassendatei korrekt, hat aber die Hauptmethode keine Signatur public static void main(String[]), so kann der Java-Interpreter keine Methode finden, bei der er mit der Ausführung beginnen soll. Verschreiben wir uns bei der main(…)-Methode in Squares, folgt die Fehlermeldung:
$ java Squares
Fehler: Hauptmethode in Klasse Squares nicht gefunden. Definieren Sie die
Hauptmethode als:
public static void main(String[] args):
oder eine JavaFX-Anwendung muss javafx.application.Application erweitern
[»] Hinweis
Der Java-Compiler und die Java-Laufzeitumgebung haben einen Schalter -help, der weitere Informationen zeigt.