Kapitel 2 Grundlagen der Java Programmierung Was macht ein Java Programm aus? Sprachbestandteile Ein erstes Programm Hauptbestandteile eines Java-Programms Vom Programmtext zur Ausführung Lesbarkeit des Programmtextes/Programmierstil Einfache Ein- und Ausgabe (Text) Import-Anweisung Ein Programm mit Ein- und Ausgabe Programmierkurs Birgit Engels, Anna Schulze ZAIK Universität zu Köln WS 07/08 1 / 69 2.1 Was macht ein Java Programm aus? 2 Fehlerhafte Programme Syntaxfehler: Der Compiler kann den Programmcode nicht korrekt übersetzen. Meist gibt der Compiler Hinweise auf den formalen Fehler. Deshalb sind diese Fehler meist “einfach” zu finden und zu beseitigen. Ein Java-Programm ist zunächst eine Textdatei, die mit einem Texteditor erstellt und bearbeitet wird und die Endung .java besitzt. Da Java eine “Sprache” darstellt, unterscheiden wir: Syntax: Formale Regeln bzw. “Grammatik”, nach denen zwischen zulässigem und ungültigem Programmcode unterschieden wird. Semantikfehler: Der Compiler übersetzt das Programm korrekt. Das übersetzte Programm arbeitet aber nicht so wie beabsichtigt. Semantikfehler sind i.a. schwieriger zu beseitigen, insbesondere bei großen Programmen. Fehlersuche durch genaue Analyse und Tests des Programms. Semantik: Inhalt des Programms, d.h. Bedeutung des Programmcodes. 3 / 69 4 2.2 Sprachbestandteile Reservierte Schlüsselwörter abstract assert boolean break byte case catch char class const continue default do Wie jede höhere Programmiersprache besteht Java aus: Schlüsselwörtern (“Wortschatz”) reservierten Zeichen (“Satzzeichen”) Namen vordefinierter Datenstrukturen, Objekte Namen selbst definierter Datenstrukturen, Objekte und Funktionen/Methoden Kommentaren double else extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while 5 / 69 Reservierte Zeichen 6 Regeln für selbstdefinierte Namen Namen (auch “Bezeichner” genannt) bestehen aus: Buchstaben a–z, A–Z // bzw. /* */: Einleitung für Kommentare. Ziffern (Zahlen) 0–9 { } : Gliederung des Programmtextes. Unterstrichen ;: Abschluss einer Anweisung. + - . . . : Arithmetische Operatoren. >= <= ==: Vergleichsoperatoren. Sie müssen mit einem Buchstaben oder beginnen. Namen, die mit beginnen, sollten vermieden werden. && k: Logische Operatoren. Sie dürfen nicht mit einem Schlüsselwort übereinstimmen. << >>: Schiebeoperatoren. Die Länge ist i.a. nicht beschränkt. Zu lange oder zu kurze Namen sollten aber vermieden werden. und weitere . . . Namen dürfen keine Leerzeichen enthalten. Zwischen Gross- und Kleinschreibung wird unterschieden! 7 / 69 8 Namensgebung Bedeutung der Namensgebung Beispiele: anzahl, knoten1, vertex, . . .: Bedeutung ersichtlich, nicht zu kurz nicht zu lang, Konvention: Kleinschreibung. Macht die Struktur des Problems bzw. Algorithmus klarer. anzKnoten, anz knoten, noVerts, . . .: Zusammengesetzt, aber mit Gross-/Kleinschreibung bzw. gut lesbar, spezifiziert “Anzahl” wegen Eindeutigkeit. anzVerts, noVertices, . . . nicht so gut, da Sprachgemisch bzw. länger als nötig. Macht Programme gut/intuitiv lesbar/erweiterbar/wartbar. Beides hilft semantische Fehler zu vermeiden/verbessern. i, j, k, p x, p y : Sehr kurze Bezeichnungen für Laufvariablen, sehr kurzzeitig (“lokal”) benötigte Variablen. Mathematische Schreibweise für mathematische Objekte (Koordinaten des Punktes p). 9 / 69 2.3 Ein erstes Programm 10 Der Programmtext “Hello World!” : HelloWorld.java 1. /* Programmierkurs WS0708 2. * ZAIK, AFS : RS, BE, AS 3. */ 4. public class HelloWorld Ziele groben Aufbau eines Programms kennenlernen 5. { groben Aufbau einer Methode kennenlernen 6. public static void main(String[] args) die Methode public static void main(String[] args) 7. { Abschluss eines jeden Befehls mit ; 8. // Ausgabe 9. System.out.println(‘‘Hello World!’’); 10. } 11. } Hello World! 11 / 69 12 Der Programmtext “Hello World!” : HelloWorld.java Der Programmtext “Hello World!” : HelloWorld.java 1. /* Programmierkurs WS0708 1. /* Programmierkurs WS0708 2. * ZAIK, AFS : RS, BE, AS 2. * ZAIK, AFS : RS, BE, AS 3. */ 3. */ 4. public class HelloWorld 4. public class HelloWorld 5. { 5. { 6. 7. Kommentare: Mehrzeilig (lang/global), public static void main(String[] args) Einzeilig (kurz/lokal). { 6. 7. Einleitung der Klassendefinition + öffnende public static void main(String[] args)und. schließende Klammer { 8. // Ausgabe 8. // Ausgabe 9. System.out.println(‘‘Hello World!’’); 9. System.out.println(‘‘Hello World!’’); 10. 10. } 11. } } 11. } Hello World! Hello World! 13 / 69 Der Programmtext “Hello World!” : HelloWorld.java 1. /* Programmierkurs WS0708 2. * ZAIK, AFS : RS, BE, AS 3. */ 4. public class HelloWorld 14 Der Programmtext “Hello World!” : HelloWorld.java Methode main gibt es in jedem Java Programm genau einmal (wieder mit öffnender und schließender Klammer). 1. /* Programmierkurs WS0708 2. * ZAIK, AFS : RS, BE, AS 3. */ 4. public class HelloWorld 5. { 5. { 6. public static void main(String[] args) 6. 7. { 7. Einziger “richtiger” Bepublic static void main(String[] fehl: Veranlasstargs) Ausgabe. { 8. // Ausgabe 8. // Ausgabe 9. System.out.println(‘‘Hello World!’’); 9. System.out.println(‘‘Hello World!’’); 10. 10. } 11. } } 11. } Hello World! Hello World! 15 / 69 Befehle enden mit Semikolon ;. 16 Der Programmtext “Hello World!” : HelloWorld.java Zeilennummern und Output 1. /* Programmierkurs WS0708 2. * ZAIK, AFS : RS, BE, AS 3. */ 4. public class HelloWorld Zeilennummern 5. { I 6. public static void main(String[] args) I 7. { 8. Output // Ausgabe 9. I I System.out.println(‘‘Hello World!’’); 10. dienen lediglich der Orientierung auf den Folien werden im Editor nicht mit eingegeben dient lediglich der Erläuterung des Programms auf den Folien wird im Editor nicht mit eingegeben } 11. } Output auf dem Bildschirm Hello World! 17 / 69 Klassendefinition 18 Hauptmethode public class HelloWorld { ...} public static void main(String[] args){} Objektorientierung: Ein “Objekt” ist für uns zunächst konkret eine Klasse. (Feinheiten später!) Eine Klasse kann viele Methoden umfassen, deren Aufbau prinzipiell immer gleich ist, jedoch nur eine Hauptmethode mit dem Methodennamen main. Daher muss jedes Programm von einer Klasse, hier class HelloWorld “umgeben” sein, d.h. der Programmtext steht zwischen den geschweiften Klammern der Klassendefinition. Hinter dem Methodennamen folgt in Klammern eine Argumentliste. Schlüsselwort public (öffentlich) bedeutet, dass diese Klasse von beliebigen anderen benutzt werden darf. Hinter der Argumentliste folgt ein Paar geschweifte Klammern, die Anweisungen umschließen. Eine (öffentliche) Klasse sollte in einer gleichnamigen Datei, hier HelloWorld.java gespeichert sein. Besonderheit von main : Soll die JVM ein Programm in Form einer Klasse X ausführen, so wird genau die Hauptmethode der Klasse gesucht und abgearbeitet. Ein Klassenname sollte mit einem Grossbuchstaben beginnen. 19 / 69 20 Schlüsselworte Befehl/Anweisung Die genaue Bedeutung und Verwendung einiger Schlüsselworte wird später behandelt, daher werden sie hier nur kurz erwähnt. System.out.println(‘‘Hello World!’’); Ist hier der Aufruf einer Methode println mit dem Argument “Hello World!”. Schlüsselwort public (öffentlich) bedeutet, dass diese Methode von beliebigen anderen Klassen benutzt werden darf. Schlüsselwort void (leer) bedeutet, dass die Methode keinen Rückgabewert hat. Veranlasst die Ausgabe von Hello World! in einer Zeile gefolgt von einem Zeilenumbruch auf die Konsole (Standardausgabe). Schlüsselwort static (statisch) bedeutet, dass dies eine Klassenmethode ist. println besteht wieder aus einer Menge von Anweisungen, die wir nicht sehen, da es eine vordefinierte Methode ist. 21 / 69 Zugriffsoperator 22 2.5 Vom Programmtext zur Ausführung Ein weiteres (besonderes) reserviertes Zeichen in Java ist der Punkt . als sogenannter Zugriffsoperator. Beispiel Wir nutzen zur Eingabe des Programmtextes einen Editor (Nutzung klar :) und zum Kompilieren/Ausführung des Programms eine Kommandozeileneingabe: System.out.println(‘‘Hello World!’’);: Die Methode println muss wie jede Methode innerhalb einer Klasse definiert sein. 1. Bearbeiten und Speichern des Programms unter <Klassenname>.java. Diese Klasse ist die Klasse out (verantwortlich für Ausgabe): out[.=etwas aus der Klasse]println(). 2. Übersetzen (Kompilieren) des Programms (einfachste Möglichkeit) mit javac <Klassenname>.java. Es entsteht eine (unleserliche) Datei <Klassenname>.class. Die Klasse out ist innerhalb der Klasse System (Systemaufgaben) definiert: System.(= besitzt die Methode/Klasse)out.(= besitzt die Methode/Klasse)println(). 3. Ausführen des Programms mit java <Klassenname>. System.out.println() ist voll qualifizierter Name der Methode println(). Um Methoden der eigene Klasse aufzurufen, reicht der einfache Methodenname. 23 / 69 24 Arbeiten auf der Konsole unter Linux Nützliche Befehle I Kompilieren/Ausführung des Programms durch Kommandozeileneingabe: Kommando ls cd path Öffnen einer “Konsole”. entspricht: Eingabeaufforderung, Terminal, ... spezieller: Shell, noch spezieller Bash, ... cd \path Eingabe eines Befehls (ggf. mit Optionen, Parametern). cd .. cd $HOME Abschluss mit Return. Effekt Listet alle Dateien in diesem Verzeichnis auf. Wechselt in den mit path angegebenen Ordner. Der Pfad wird immer vom aktuellen Verzeichnis aus interpretiert. Wechselt in den mit path angegebenen Ordner. Der Pfad wird jetzt von der Verzeichniswurzel ausgehend interpretiert. Wechselt in den Elternordner des aktuellen Ordners. Wechselt in das Home(-Verzeichnis) des Benutzers. 25 / 69 Nützliche Befehle II Kommando mkdir name cp file path cp file file1 cp -r/R path path1 cp -r/R path . 26 Nützliche Befehle III Effekt Legt im aktuellen Verzeichnis einen neuen Ordner namens name an. Kopiert die Datei file an die Stelle path. Legt eine Kopie der Datei file unter dem Namen file1 an. Kopiert das ganze Verzeichnis path samt Inhalt nach path1. Kopiert das ganze Verzeichnis path nach “hier”, d.h. in das akltuelle Verzeichnis. Kommando rm file rm -r/R name rmdir name mv file file1 mv file path mv name name1 27 / 69 Effekt Die Datei file wird gelöscht. Das Verzeichnis name wird mit allen Unterverzeichnissen und Dateien gelöscht. Das leere (!) Verzeichnis name wird gelöscht. Benennt die Datei file in file1 um. (Die Endung wird nicht automatisch beibehalten Verschiebt die Datei die Datei file an die Stelle path. Benennt das Verzeichnis name in name1 um. 28 Hilfsoptionen Tipps Durch Drücken der Tab-Taste werden unvollständig eingegebene Befahle ergänzt, falls eindeutig möglich. (Sonst werden mehrere Möglichkeiten oder gar nichts angezeigt.) Hilfsoptionen zu einzelnen Befehlen (nicht bei allen verfügbar): Kommando man command command -h/-help/- -help Pfeiltasten (↑, ↓) können vorherige/ spätere Kommandos wieder ausgewählt werden. Effekt Zeigt “Manual Page” (Handbuch) des Befehls command an. Zeigt Optionen/Benutzung des Befehls command an. Soll das gleiche Kommando für viele Dateien mit ähnliche Namen ausgeführt werden, können sogenannte wild cards Platzhalter, z.B. “*” benutzt werden, um die unterschiedlichen Namensteile zu ersetzen. Der Befehl, wird dann für alle Dateien ausgeführt, die in das Namensmuster passen. Beispiel: Kommando cp java/*.java . Effekt Kopiert alle Dateien mit Endung “.java” nach hier. 29 / 69 Java-Kommandos 30 Das SSH-Kommando Das Secure Shell Kommando (ssh) dient dem Einloggen auf Rechnern über das Netzwerk. Kommando javac file.java java file Wird zur Zeit im Pool selbst verwendet, um sich vom eigenen Arbeitsplatzrechner auf einen Server einzuloggen. Effekt Kompiliert file.java. Erzeugt Datei file.class. Führt die kompilierte Datei file.class aus. Kann auch von eigenem Rechner mit entsprechendem Netzzugang genutzt werden, um auf den Server zu gelangen. Kommando: Kommando ssh username@servername 31 / 69 Effekt Erzeugt (nach Passworteingabe für username) eine Konsole auf dem Server servername. 32 SSH von zu Hause/Server Das SCP-Kommando Unter Linux ist meist ssh standardmässig installiert, d.h. auf der heimischen Konsole kann man sich mit ssh- Kommando auf den Uni-Server einloggen. Das SCP Kommando (scp) ist das Netzwerk-Pendant zum einfachen Kopier-Kommando (cp). Kann auf einer heimischen Linuxkonsole (standard mässig) direkt zum kopieren von Dateien in sein Uni-Home auf dem Uni-Server verwendet werden. Unter Windows installiert man meist einen SSH-Client extra (siehe Website). Servernamen: Wird unter Windows meistens von graphischen Oberflchen benutzt/unterstützt (siehe SSH-Client, Website). sunfire.rrz.uni-koeln.de dialog.rrz.uni-koeln.de 33 / 69 Verwendung von scp Kommando scp username@servername : path/file . scp file username@servername : path . 34 Hinweis zu scp Liegt die Datei file direkt im Uni-Home entfällt path. Der Pfad path wird ansonsten relativ zum Home-Verzeichnis angegeben Effekt Lädt die Datei file vom Server auf den eigenen Rechner. Lädt die Datei file vom eigenen Rechner auf den Server. Beispiel: xxx.java liegt im Homeverzeichnis, Unterverzeichnis JavaKram. Folgender Befehl kopiert die Datei auf den eigenen Rechner: scp username@servername : JavaKram/xxx.java . Bei Benutzung von ssh im PC-Pool müssen Dateien nicht hin und her kopiert werden!!! Auf dem Server stehen die gleichen Dateien (Home-Verzeichnis) zur Verfügung wie am Arbeitsplatzrechner!!! 35 / 69 36 2.5 Vom Programmtext zur Ausführung Erste Hindernisse Falls bei Schritt 2 Fehler auftreten: Command not found oder Ähnliches: Kein Java-Compiler installiert oder javac wird nicht gefunden (liegt nicht im vordefinierten Pfad). Abhilfe: Mit which javac (Linux) bzw. where javac (Windows) den Pfad suchen und mit Pfad aufrufen bzw. Pfad setzen. Falls kein Java-Compiler gefunden: Installation... Wir nutzen zur Eingabe des Programmtextes einen Editor (Nutzung klar :) und zum Kompilieren/Ausführung des Programms eine Kommandozeileneingabe: 1. Bearbeiten und Speichern des Programms unter <Klassenname>.java. 2. Übersetzen (Kompilieren) des Programms (einfachste Möglichkeit) mit javac <Klassenname>.java. Es entsteht eine (unleserliche) Datei <Klassenname>.class. cannot read: <Klassenname>.java oder Ähnliches: Die zu kompilierende Datei liegt nicht im aktuellen Verzeichnis. Abhilfe: Mit cd <Pfad> in das entsprechende Verzeichnis wechseln oder mit javac -classpath <Pfad> <Klassenname>.java kompilieren. 3. Ausführen des Programms mit java <Klassenname>. Letztere Möglichkeit wird auch beim Verwenden von Paketen (später) angewendet. 37 / 69 Kompilier-Fehler 38 Laufzeit-Fehler Auch bei Schritt 3 treten Fehler auf: Am häufigsten treten jedoch vom Compiler gemeldete Syntaxfehler auf. Class definition not found oder Ähnliches: Pfadprobleme oder Ähnliches (s.o.) Diese sind meist mit Zeilenangabe versehene Kurzbeschreibung zur Fehlersuche im Programmtext. Fehler beim Linken/Einbinden von mehreren selbsdefinierten Klassen (mehrere Dateien), Pfadprobleme, Bibliotheken (Später). Häufige Fehler sind: Tippfehler Semantikfehler: Unerwartetes Ergebnis, Programm “stürzt ab”. Vergessene “;” “{” “}” Fehlende/Mehrfache Deklaration (später) Hinweise zur Benutzung des Compilers (Optionen, Linken, etc.) mit: javac --help Falscher Methodenaufruf (später) 39 / 69 40 2.6 Lesbarkeit des Programmcodes Kürzere Formulierung möglich Java-Programme werden durch die Zeilenstruktur und Extra-Leerzeichen nicht beeinflußt. Kommentare erläutern Programm Ausnahme: Mit // eingeleitete Kommentare enden mit dem Zeilenumbruch! verbessern Lesbarkeit werden vom Compiler ignoriert Daher: Obige Funktion könnte man kürzer formulieren: einzeilige Kommentare werden mit // eingeleitet mehrzeilige Kommentare beginnen mit /* und enden mit */ public class HelloWorld { public static void main(String args) { System.out.println(‘‘Hello World!’’); }} Wichtig: In eigenen Programmen oft und ausführlich kommentieren! Nicht empfehlenswert ! 41 / 69 Lesbarkeit 42 Groß- und Kleinschreibung Durch Einfügen von Leerzeilen und durch Einrückung kann die Lesbarkeit stark gesteigert werden. Deshalb sollte man Folgendes beachten: Durch Leerzeilen sinnvoll gliedern Java ist case-sensitive, unterscheidet also zwischen Großund Kleinbuchstaben! Nur ein Befehl je Zeile X ist nicht dasselbe wie x, Main() ist nicht dasselbe wie main() Jedes { und } in eine eigene Zeile Nach jedem { um 2 Zeichen einrücken Geht ein Befehl über mehrere Zeilen, die folgenden Zeilen einrücken 43 / 69 44 2.7 Einfache Ein- und Ausgabe Ausgabe - Tipps System.out.println(’’Die Zeile ist zuuuuuu‘‘ +’’lang.‘‘): Schon bekannt: Ein Ausgabe-Befehl: System.out.println(‘‘Ausgabe und Zeilenumbruch‘‘) I I Die Zeile ist zuuuuuu lang. System: Automatisch in jedem Java-Programm verfügbare Klasse (Standardbibliothek). out: Instanz der Klasse PrintStream, automatisch in System enthalten, Verknüpft mit Standardausgabe (Bildschirm). int var=1; System.out.println(’’var=‘‘ +var+ ’’ Okay.‘‘): var=1 Okay. Abgewandelte Ausgabe-Befehle: System.out.println(): Zeilenumbruch System.out.print(‘‘Ausgabe‘‘): Ausgabe Ausgaben sind einfache Mittel zur Suche nach logischen Fehlern: System.out.print(’’\ n‘‘): Zeilenumbruch I I Ausgabe einer Variablen: Hat sie den richtigen Wert ? Ausgabe in bestimmter Zeile: Wird das Programm bis hierhin abgearbeitet ? 45 / 69 Eingabe 2.8 Import-Anweisung Um eine Eingabe von der Kommandozeile einzulesen und in unserem Programm zu verarbeiten, benötigen wir weitere vordefinierte Java-Klassen: Die beschriebene Eingabe-Klassen, gehören nicht zu den automatisch ansprechbaren Klassen. BufferedReader, InpuStreamReader: 2 Klassen, um Zeichenketten (gepuffert) einzulesen. Sie gehören zum ”Paket“ java.io Diese Paket muss explizit im Programmtext angegeben werden, um die Eingabe-Klassen zu verwenden. System.in: Das Objekt in aus der Klasse System. Alle Elemente dieses Paketes werden mit folgender Anweisung (Importanweisungen) eingebunden: Ein vorbereitendes Programmstück: BufferedReader in = new BufferedReader new InputStreamReader(System.in) ); 46 ( import io.*; Eigentlicher Einlese-Befehl: String name = in.readLine(); 47 / 69 48 Import-Anweisung 2.9 Ein Programm mit Ein- und Ausgabe Ziele Sogenannte Importanweisungen stehen immer als erstes (außerhalb der Klassendefinition) im Programmtext. Eingabe als komplexere Anweisung anwenden können. Dort werden Sie vom (Prä)prozessor gefunden und verarbeitet. Erste Ausnahme/Exception. Import-Anweisung benutzen, da für Eingabe notwendig. Erste Verwendung einer Variable. 49 / 69 Ein Grussprogramm I: Greets.java 50 Ein Grussprogramm I: Greets.java 1. /* Programmierkurs WS0708 AFS RS, BE, AS */ 1. /* Programmierkurs WS0708 AFS RS, BE, AS */ 2. import java.io.*; 2. import java.io.*; 3. public class Greets 3. public class Greets 4. { 4. { 5. 6. 7. 8. 9. 10. 5. public static void main(String[] args) 7. { 8. BufferedReader in = new BufferedReader 9. ( new InputStreamReader(System.in) ); 10. System.out.println( ’’What’s your name ? ‘‘); 51 / 69 vor public static void main(String[] args) 6. throws IOException Import-Anweisung Klassendefinition! throws IOException { BufferedReader in = new BufferedReader ( new InputStreamReader(System.in) ); System.out.println( ’’What’s your name ? ‘‘); 52 Ein Grussprogramm I: Greets.java Ein Grussprogramm I: Greets.java 1. /* Programmierkurs WS0708 AFS RS, BE, AS */ 1. /* Programmierkurs WS0708 AFS RS, BE, AS */ 2. import java.io.*; 2. import java.io.*; 3. public class Greets 3. public class Greets 4. { 4. { 5. 6. 7. 8. 9. 10. 5. public static void main(String[] args) public static void main(String[] args) 6. throws IOException Ausnahme: Fehler{ behandlung Wird BufferedReader in = new BufferedReader bei Verwendung der ( new InputStreamReader(System.in) ); EingabeKlassen verlangt System.out.println( ’’What’s your(Später). name ? ‘‘); 7. Lange Befehle: 2-zeilig und eingerückt. throws IOException { 8. BufferedReader in = new BufferedReader 9. ( new InputStreamReader(System.in) ); 10. System.out.println( ’’What’s your name ? ‘‘); 53 / 69 Grussprogramm II 54 Grussprogramm II Einlesen in Variable name vom Typ String. 1. // Tastatureingabe einlesen! 1. // Tastatureingabe einlesen! 2. String name = in.readLine(); 2. String name = in.readLine(); 3. System.out.println(); 3. System.out.println(); 4. System.out.println(’’Buon Giorno,‘‘+ name); 4. System.out.println(’’Buon Giorno,‘‘+ name); 5. 5. } } 6. } 6. } 55 / 69 56 Grussprogramm II 1. // Tastatureingabe einlesen! 2. String name = in.readLine(); 3. System.out.println(); 4. System.out.println(’’Buon Giorno,‘‘+ name); 5. Grussprogramm II // Tastatureingabe einlesen! 2. String name = in.readLine(); 3. System.out.println(); 4. System.out.println(’’Buon Giorno,‘‘+ name); 5. } } 6. } 6. } What’s your name ? Nemo ←- What’s your name ? 57 / 69 Grussprogramm II 1. // Tastatureingabe einlesen! 2. String name = in.readLine(); 3. System.out.println(); 4. System.out.println(’’Buon Giorno,‘‘+ name); 5. 1. } 6. } What’s your name ? Nemo Buon Giorno, Nemo 59 / 69 58