From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+Eine neue Programmiersprache lernt man nur, wenn man selbst Programme
+in dieser Sprache schreibt. Je mehr, desto besser. Bei der Lektüre
+des Buchs ist es daher sinnvoll, von Anfang an eigene Experimente
+durchzuführen und so viele Beispielprogramme wie möglich
+auszuprobieren, abzuändern, zu übersetzen und auszuführen.
+In diesem Abschnitt wollen wir ein paar informelle Tipps geben, die
+das erleichtern sollen.
+
+
+Hier noch einmal in Kurzform die Schritte vom Quellcode bis zum lauffähigen
+Programm:
+
+Für die ersten Schritte in einer neuen Sprache benötigt
+man immer auch I/O-Routinen, um einfache Ein- und Ausgaben vornehmen
+zu können. Glücklicherweise kann man in Java nicht nur grafikorientierte
+Programme schreiben, sondern auch auf die Standardein- und -ausgabe
+zugreifen. Damit stehen für kleine Programme einfache I/O-Routinen
+zur Verfügung, die wie in den meisten konventionellen Programmiersprachen
+verwendet werden können.
+
+
+Mit Hilfe des Kommandos System.out.println
+können einfache Ausgaben auf den Bildschirm geschrieben werden.
+Nach jedem Aufruf wird ein Zeilenumbruch ausgegeben. Mit System.out.print
+kann diese auch unterdrückt werden. Beide Methoden erwarten ein
+einziges Argument, das von beliebigem Typ sein kann. Dieses kann jedoch
+auch zur Laufzeit mit Hilfe des Plus-Operators aus verschiedenen Bestandteilen
+zusammengefügt werden:
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 2 - Schnelleinstieg
+
+
+
+
+
+2.3 Tipps für eigene Experimente
+
+
+
+
+
+
+
+
+2.3.1 Der Entwicklungszyklus in Kurzform
+
+
+
+
+
+
+
+
+2.3.2 Einfache Ausgaben
+
+
+
+
+Listing 2.2: Einfache Ausgaben
+
+
+
+
+
+001 /* Listing0202.java */
+002
+003 public class Listing0202
+004 {
+005 public static void main(String[] args)
+006 {
+007 System.out.println("1+2=" + (1+2));
+008 }
+009 }
+
+
+Listing0202.java
+
+Die Ausgabe des Programms ist:
+
+
+1+2=3
+
+
+
+
![]() |
+
+
+ +Der erste String enthält den Wert »1+2=« und wird mit +dem Ergebnis des Ausdrucks (1+2) verkettet (also mit dem Wert +3). Ohne die Klammern würde der Compiler das zweite Plus ebenfalls +als String-Verkettungsoperator ansehen und die Ausgabe des Programms +wäre 1+2=12 gewesen. |
+
+
|
+![]() |
+
+
![]() |
+![]() |
+
+
+ +Seit Java 6 gibt es ein printf-Pendant, +das in Abschnitt 11.6.2 beschrieben +wird. Es bietet ähnliche Funktionen wie die entsprechenden C-Routinen +und stellt eine flexible und einfach zu bedienende Ausgabeschnittstelle +zur Verfügung. |
+
+
|
+![]() |
+
+Seit der Version Java 5 ist auch das Einlesen von Daten über +die Kommandozeile ein Kinderspiel. Hierzu verwenden man statt des +Ausgabe-Streams System.out +den Eingabe-Stream System.in +in Verbindung mit einer Instanz der Hilfsklasse Scanner. + +
+Das folgende Listing zeigt ein Programm, das zwei Ganzzahlen einliest, +sie zusammenzählt und das Ergebnis auf dem Bildschirm ausgibt: + + +
+
+
+
+001 /* Listing0203.java */
+002
+003 import java.util.Scanner;
+004 import java.io.IOException;
+005
+006 public class Listing0203
+007 {
+008 public static void main(String[] args)
+009 throws IOException
+010 {
+011 int a, b, c;
+012
+013 Scanner scanner = new Scanner(System.in);
+014
+015 System.out.println("Bitte a eingeben: ");
+016 a = scanner.nextInt();
+017 System.out.println("Bitte b eingeben: ");
+018 b = scanner.nextInt();
+019 c = a + b;
+020 System.out.println("a+b="+c);
+021 }
+022 }
+
+ |
++Listing0203.java | +
+
![]() |
+
+
+ +Die import-Anweisung +am Anfang des Listings dient dazu, die Klasse Scanner +des Paketes java.util +bekanntzumachen. Ohne diese Anweisung würde Scanner +vom Compiler nicht gefunden und es gäbe eine entsprechende Fehlermeldung. +Auch in nachfolgenden Beispielprogrammen tauchen von Zeit zu Zeit +import-Anweisungen +auf. In Kapitel 13 werden +wir ausführlich auf die Verwendung und das Erstellen von Paketen +eingehen. |
+
+
|
+![]() |
+
+Werden die Zahlen 10 und 20 eingegeben, so lautet die Ausgabe des
+Programms:
+
+
+Bitte a eingeben:
+10
+Bitte b eingeben:
+20
+a+b=30
+
+
+
+
![]() |
+![]() |
+
+
+ +Das Ergebnis von scanner.nextInt +ist ein Integer, +der den Inhalt der Eingabezeile enthält. |
+
+
|
+![]() |
+
+Weitere Informationen zur streambasierten Ein-/Ausgabe sind in Kapitel 18 +und Kapitel 19 zu finden. + + + + +
+Es ist bekannt, dass man sich über die Formatierung von Quelltexten +und die Einrückung von Deklarationen und Anweisungen streiten +kann. Jeder Entwickler hat seinen eigenen Stil und kennt gute Argumente, +genau diesen zu verwenden. Bei Java-Programmen gibt es einige große +Lager, denen man sich anschließen kann. Im professionellen Umfeld +ist man sogar meist gezwungen, sich einem vorgegebenen Stil anzupassen. +Wir wollen uns diesen fruchtlosen Diskussionen nicht anschließen +und keinesfalls behaupten, die in diesem Buch verwendete Art der Quelltextformatierung +wäre die einzig richtige. Wir haben jedoch versucht, die Beispielprogramme +konsistent zu formatieren und dabei einige wenige, leicht verständliche +Regeln einzuhalten. + +
+Bei Klassen- und Methodendefinitionen stehen die geschweiften Klammern +unterhalb der Deklarationsanweisung, und die eigentliche Deklaration +ist eingerückt: + + +
+
+
+
+001 import java.util.Scanner;
+002
+003 public class Listing0204
+004 {
+005 public static void main(String[] args)
+006 {
+007 //Hier steht der Methodenrumpf
+008 }
+009 }
+
+ |
+
+Bei Kontrollanweisungen innerhalb einer Methode schreiben wir die +öffnende Klammer dagegen in dieselbe Zeile wie die einleitende +Anweisung: + + +
+
+
+
+001 for (int i = 0; i < aNeighbours.length; ++i) {
+002 if (p1.x + aNeighbours[i][0] == p2.x) {
+003 if (p1.y + aNeighbours[i][1] == p2.y) {
+004 return true;
+005 }
+006 }
+007 }
+
+ |
+
+Dies gilt auch für fortgesetzte Anweisungen wie beispielsweise +else +oder else if: + + +
+
+
+
+001 if (cmd.equals("Größer")) {
+002 d.height *= 1.05;
+003 d.width *= 1.05;
+004 } else if (cmd.equals("Kleiner")) {
+005 d.height *= 0.95;
+006 d.width *= 0.95;
+007 } else {
+008 x = 10;
+009 }
+
+ |
+
+Diese Technik verwenden wir meist auch, wenn bei einem Methodenaufruf +nicht alle Argumente in eine Zeile passen: + + +
+
+
++001 System.out.println( +002 "Grüße aus Hamburg".regionMatches( +003 8, +004 "Greetings from Australia", +005 8, +006 2 +007 ) +008 );+ + |
+
+Diese einfachen Regeln lassen sich in den meisten Fällen anwenden, +es gibt aber auch Fälle, in denen sie versagen. So zum Beispiel, +wenn der Testausdruck einer if-Anweisung +über mehrere Zeilen geht, wenn die Parameterdeklaration einer +Methode nicht in eine Zeile passt oder schlicht, wenn die Verschachtelung +bereits sehr tief ist und keine weitere Einrückung zuläßt. +In diesem Fall sei der Leser um Nachsicht gebeten und aufgefordert, +den ästhetischen Anspruch an das Programm den jeweiligen pragmatischen +Erwägungen unterzuordnen. + + + + +
+Wie in allen Programmiersprachen, gibt es auch in Java Konventionen +für die Vergabe von Namen. Sie sind zwar nicht zwingend erforderlich, +erleichtern aber das Verständnis der Quelltexte ungemein und +sollten daher unbedingt eingehalten werden. Die wichtigsten sind: +
+Weitere Konventionen werden, wenn erforderlich, im Buch beschrieben. + + + + +
+Immer wieder wird gefragt, wie man Java-Programme möglichst einfach +unter Windows aufrufen kann. Das Starten aus der DOS-Box erscheint +vielen Lesern zu umständlich, und bei einem Java-Programm mit +grafischer Oberfläche stört das überflüssige Konsolenfenster. +Im Gegensatz zu com- oder exe-Dateien +ist ein kompiliertes Java-Programm zwar nicht direkt ausführbar, +aber es gibt doch einige Möglichkeiten, das Starten unter Windows +zu vereinfachen. + + + + +
+Eine erste Vereinfachung besteht darin, eine Batchdatei zu erstellen,
+aus der der java-Interpreter mit dem Java-Programm als Argument aufgerufen
+wird. Soll beispielsweise das Java-Programm Listing3701,
+dessen Bytecode Listing3701.class im
+Verzeichnis c:\tmp liegt, mit dem java-Interpreter,
+der in das Verzeichnis c:\jdk1.6 installiert
+wurde, gestartet werden, kann dazu folgende Batch-Datei verwendet
+werden:
+
+
+@echo off
+c:
+cd \tmp
+c:\jdk1.6\bin\java Listing3701
+
+
+
+
+Wird diese beispielsweise go3701.bat +genannt und in ein Verzeichnis gelegt, das über die PATH-Angabe +zu erreichen ist, kann unser Java-Programm durch einfache Eingabe +des Kommandos go3701 aus jedem +Verzeichnis heraus oder aus dem »Ausführen«-Dialog +des Startmenüs gestartet werden. + + + + +
+Ebenso leicht ist es möglich, ein Java-Programm durch einen Doppelklick +auf ein Desktop-Symbol zu starten. Dazu wird eine Verknüpfung + angelegt, die den java-Interpreter mit dem +Programmnamen als Argument aufruft. Nach einem rechten Mausklick auf +den Windows-Desktop ist dazu zunächst der Menüpunkt »Neu.Verknüpfung« +aufzurufen. Anschließend sind die Angaben für Programm, +Arbeitsverzeichnis und Icon so zu machen, dass der spätere Eigenschaften-Dialog +des neu angelegten Symbols wie folgt aussieht (beispielhaft für +Windows 98 und die Version 1.4 des JDK): +
+ +
+Abbildung 2.5: Eine Verknüpfung auf dem Windows-Desktop
+ ++Das Java-Programm kann nun wie jedes andere Windows-Programm per Doppelklick +vom Desktop aus gestartet werden. + + + + +
+Soll ein java-Programm, das eine grafische Oberfläche hat, ohne +Konsolenfenster gestartet werden, kann anstelle des Standard-Interpreters +java +der alternative Interpreter javaw +verwendet werden. Er arbeitet genauso wie java +und akzeptiert dieselben Optionen (siehe Abschnitt 51.2), +stellt der Anwendung aber kein Konsolenfenster zur Verfügung. +Zu beachten ist allerdings, dass alle Ausgaben auf System.out +und System.err +ins Leere gehen. + + + + +
+Nachfolgend noch einmal eine kurze Zusammenfassung der häufigsten +Probleme beim Erstellen, Übersetzen und Starten eines Java-Programms, +inklusive Beschreibung, wie man sie behebt oder umgeht. + + + + +
+Alle Werkzeuge des JDK arbeiten kommandozeilenorientiert. Anders als +typische GUI-Programme wie Adobe Photoshop, Microsoft Excel oder Netscape +Navigator besitzen sie also keine grafische Oberfläche, sondern +werden aus einer »DOS-Box« (bzw. einer UNIX-Shell) heraus +aufgerufen. Diese wird unter Windows-Betriebssystemen als »MS-DOS-Eingabeaufforderung« +bezeichnet und ist meist im Startmenü (unter »Programme«) +zu finden. In der DOS-Box werden Befehle und ihre Parameter über +die Tastatur eingegeben und starten so die zugehörigen Programme. +Um in einer DOS-Box zurecht zu kommen, sollte man deren Kommandosyntax +und die wichtigsten Befehle zum Starten von Programmen und für +Datei- und Verzeichnisoperationen kennen. Beides wird in unzähligen +Büchern und (zum Teil) in den Hilfedateien des Betriebssystems +beschrieben. +
+
![]() |
+
+
+ +Das UNIX-Pendant zu einer DOS-Box ist die Shell. +Auch sie dient primär dazu, Benutzerkommandos zu empfangen und +auszuführen. UNIX-Shells sind wesentlich mächtiger als DOS-Boxen +unter Windows, und im Laufe der Jahre haben sich verschiedene Varianten +entwickelt (Bourne-Shell, C-Shell, Korn-Shell, BASH etc.). Obwohl +viele der elementaren Shell-Kommandos den DOS-Box-Pendants gleichen +oder ihnen recht ähnlich sind, lassen sich mit ihrer detaillierten +Beschreibung leicht ganze Bücher füllen. Das Kommando man +liefert eine Beschreibung der Shell und aller zugehörigen UNIX-Kommandos. |
+
+
|
+![]() |
+
+Wer nicht kommandozeilenorientiert arbeiten will, kann statt der im +Buch beschriebenen JDK-Werkzeuge natürlich auch eine integrierte +Entwicklungsumgebung zum Erlernen der Java-Programmierung verwenden +(z.B. Borland JBuilder). In diesem Fall stehen Editor, Compiler, Interpreter +und alle anderen Werkzeuge unter einer gemeinsamen und einheitlichen +grafischen Oberfläche zur Verfügung und können auf +Knopfdruck gestartet werden. Der Nachteil dieser integrierten Werkzeuge +ist allerdings eine etwas höhere Einarbeitungszeit, denn von +der Vielzahl der Möglichkeiten wird man zunächst erschlagen. +Zudem sind wichtige Techniken und Arbeitsschritte oftmals hinter Hilfsprogrammen +und Assistenten verborgen und erschweren so das Verständnis grundlegender +Konzepte. + + + + +
+Wenn unter Windows der Java-Interpreter java +gestartet werden kann, beim Aufruf des Compilers javac +aber eine Fehlermeldung kommt, liegt das meist daran, dass der PATH +nicht korrekt gesetzt wurde. Während die JDK-Installation den +Interpreter unter anderem auch in Verzeichnisse kopiert, auf die der +PATH bereits verweist (so dass dieser ohne weiteres Zutun aus jedem +Verzeichnis aufgerufen werden kann), ist das für den Compiler +und die übrigen JDK-Werkzeuge nicht der Fall. Diese können +nur dann ohne vorangestellten Pfad aufgerufen werden, wenn der PATH +auf das Unterverzeichnis bin des Installationsverzeichnisses +verweist. Bei der in diesem Buch angenommen Standard-Installation +muss die PATH-Variable +also das Verzeichnis c:\jdk1.6\bin enthalten. + + + + +
+Einer der Standardmechanismen zur Konfiguration von Programmen besteht +darin, Umgebungsvariablen zu setzen. Diese werden vom Anwender (meist +innerhalb einer DOS-Box bzw. Shell mit Hilfe des set-Kommandos) +gesetzt und vom Programm gelesen und zur Konfiguration verwendet. +Die beiden für das JDK wichtigsten Umgebungsvariablen sind PATH +und CLASSPATH. +Über Erstere wird dem Betriebssystem mitgeteilt, wo es nach ausführbaren +Programmen suchen soll, also etwa nach dem Compiler oder Interpreter +des JDK. Die Umgebungsvariable CLASSPATH +(umgangssprachlich »der CLASSPATH« genannt) ist JDK-spezifisch. +Sie zeigt dem Compiler und Interpreter an, in welchen Verzeichnissen +er nach Klassendateien suchen soll. Im Gegensatz zu PATH +kann der CLASSPATH +bei der Standardinstallation eines aktuellen JDKs (Version 1.3 oder +später) ungesetzt bleiben. Compiler und Interpreter finden ihr +eigenes Laufzeitsystem automatisch, und die selbst geschriebenen Klassen +werden im aktuellen Verzeichnis gesucht. + +
+Da es zu umständlich ist, häufig benötigte Umgebungsvariablen +nach jedem Aufruf einer DOS-Box neu zu setzen, bieten alle Betriebssysteme +die Möglichkeit, sie permanent festzulegen. Abschnitt 2.1.2 +erläutert dies am Beispiel der PATH-Variable. + + + + +
+Wenn der Compiler javac +die .java-Datei nicht findet, liegt dies +in aller Regel daran, dass sie nicht existiert. Der Compiler unterscheidet +zwischen Groß- und Kleinschreibung; die Datei Test1.java +ist somit streng von test1.java oder +TEST1.JAVA zu unterscheiden. Zudem muss +die Dateierweiterung .java lauten, denn +andere Erweiterungen werden nicht akzeptiert. Hat der Editor fälschlicherweise +die Erweiterung .txt angehängt, +wird die Datei vom Compiler nicht gefunden. Mitunter kommt es auch +vor, dass Beispieldateien beim Kopieren oder Entpacken in das MS-DOS-8.3-Format +konvertiert werden. Die Datei Test1.java +würde dann TEST1.JAV heißen +und vom Compiler nicht akzeptiert werden. + +
+Wichtig ist auch, dass der Compiler korrekt aufgerufen wird. Anders +als beim Interpreter wird die Dateierweiterung stets angegeben. Ein +Aufruf von javac Test1 wird +also nicht funktionieren, javac Test1.java +dagegen sehr wohl. Schließlich ist zu beachten, dass die zu +übersetzende Klasse denselben Basisnamen hat wie die Datei, in +der sie definiert wurde. In der Datei Test1.java +muss also eine öffentliche Klasse mit dem Namen Test1 +definiert worden sein. + + + + +
+Der häufigste Fehler beim Aufruf des Interpreters ist ein »NoClassDefFoundError«. +Ein trivialer Fehler besteht darin, dass der Interpreter falsch aufgerufen +wurde. Im Gegensatz zum Compiler möchte er keinen Dateinamen +als Argument übergeben bekommen, sondern einen Klassennamen. +Folglich darf die Erweiterung .java oder +.class nicht angegeben werden. Die in +die Datei Test1.class übersetzte +Klasse Test1 wird also durch +Aufruf von java Test1 gestartet, +und nicht durch java Test1.class. + +
+Das funktioniert allerdings nur, und das ist auch schon die zweite +Fehlerquelle, wenn Test1 auch +tatsächlich eine Methode public static +void main enthält. Diese versucht nämlich der +Interpreter zu starten, und wenn sie nicht vorhanden ist, gibt es +obige Fehlermeldung. + +
+Ist der Aufruf korrekt und die main-Methode +ebenso vorhanden wie die nötige Klassendatei, kann es trotzdem +vorkommen, dass der Interpreter die Klasse nicht starten kann. Das +liegt dann meist daran, dass etwas mit dem CLASSPATH +nicht stimmt. Der CLASSPATH +ist eine Umgebungsvariable, die eine Liste von Verzeichnissen und +Archivdateien enthält, die vom Interpreter der Reihe nach durchsucht +werden, um die auszuführenden Klassen zu finden. Die genaue Interpretation +des CLASSPATH +hat sich über die Jahre etwas geändert, aber bei aktuellen +JDK-Versionen kann sie wie folgt zusammengefasst werden: + +
+Ist gar kein CLASSPATH +angegeben, sucht der Interpreter im aktuellen Verzeichnis (bzw. +bei Klassen in Unterpaketen in darin befindlichen Unterverzeichnissen) +nach der Klassendatei. Ist dagegen eine Umgebungsvariable CLASSPATH +vorhanden, durchsucht der Interpreter dessen Elemente der Reihe nach. +Befindet sich darin nicht das aktuelle Verzeichnis (entweder +absolut oder als ».« angegeben), so werden auch keine Klassen +gefunden, die im aktuellen Verzeichnis liegen. Für unsere ersten +Versuche ist es bei aktuellen JDKs also am besten, den CLASSPATH +gar nicht zu setzen und alle Klassen in das aktuelle Verzeichnis zu +legen. + +
+Mitunter wird der CLASSPATH +von anderen installierten Java-Programmen verändert und sorgt +so unbeabsichtigt dafür, dass die eigenen Klassen nicht mehr +gefunden werden. Das ist zwar kein guter Stil, kommt in der Praxis +aber dennoch manchmal vor. In einem solchen Fall muss der CLASSPATH +während der eigenen Experimente zurückgesetzt oder so geändert +werden, dass das aktuelle Verzeichnis (bzw. das mit den eigenen Klassendateien) +darin enthalten ist. +
+
![]() |
+
+
+ +Neben der CLASSPATH-Umgebungsvariable +kann der Klassenpfad dem Compiler und Interpreter auch direkt beim +Aufruf über Kommandozeilenschalter bekanntgemacht werden (die +entsprechenden Argumente lauten -cp +bzw. -classpath). +Werden also beispielsweise Compiler und Interpreter über Batch-Dateien +bzw. Shell-Scripte aufgerufen, könnten darin entsprechende Parameter +enthalten sein und das Auffinden der eigenen Klassen erfolgreich verhindern. +Auch dies ist eine Fehlerquelle, die in der Praxis mitunter eine Rolle +spielt. |
+
+
|
+![]() |
+
+Gibt es beim Ausführen eines Beispielprogramms die Fehlermeldung, +dass eine andere als die aufgerufene Klasse nicht gefunden werden +kann, liegt das meist daran, dass deren .class-Datei +nicht mit aus dem Verzeichnis mit den Beispieldateien in das aktuelle +Verzeichnis kopiert wurde. Prominentester Kandidat ist der WindowClosingAdapter, +der von fast allen Beispielprogrammen benötigt wird, die eine +grafische Oberfläche haben. Weitere Hinweise sind in Abschnitt 2.2.2 +zu finden. +
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |