Inhalt Was ist Java? Linux und KDE in den Terminalräumen Technische Universität Braunschweig Institut für Wissenschaftliches Rechnen Erste Schritte mit Java ”Turtle” - Programme mit den EIP classes Fortgeschrittene Sprachkonzepte Einführung in das Programmieren – Primitive Datentypen – Arithmetische Operatoren – Die for - Schleife – Prozeduren – Funktionen Braunschweig, den 26. Oktober 2003 Einführung in das Programmieren Inhalt 3/249 – Weitere Schleifen – Relationale Operatoren – Logische Operatoren – Bedingungen Dieser Workshop wird begleitend zum Praktikum ”Einführung in das Programmieren” angeboten. – Felder Ziel soll es sein, anfängliche Probleme und Schwierigkeiten beim Einstieg in die Programmierung zu überwinden. Endliche Automaten Referenztypen Darüber hinaus werden die Informationen, die auf den Aufgabenblättern gegeben werden, erläutert und der Verständnishindergrund geschaffen, um die Programmieraufgaben zu bewältigen. Objektorientierung Applets Dokumentation Einführung in das Programmieren 2/249 Einführung in das Programmieren 4/249 Was ist Java? Java ist eine in den frühen 90ern entstandene Programmiersprache der Firma Sun. Dieses Skript wurde von Christian Berger für das Institut für Wissenschaftliches Rechnen im Jahre 2003 verfasst. Es basiert auf folgender Literatur: [Krü03], [CU03], [DWS02], [NM97] und [SM03]. Einführung in das Programmieren Der offiziellen Beschreibung nach ist Java eine einfache, objektorientierte, verteilte, interpretierte, robuste, sichere, architekturneutrale, portable, performante, nebenläufige und dynamische Programmiersprache. 5/249 Einführung in das Programmieren 7/249 Was ist Java? Praktisch bedeutet es, dass man Programme in Java schreiben kann, die auf Handies laufen, aber auch Programme, die sinnvollerweise nur auf Hochleistungsrechnern ausgeführt werden sollten. Was ist Java? Häufig trifft man Java-Programme in Form von Applets, die bewegten Inhalt darstellen oder der Benutzerkommunikation (z.B. in Form von Online Banking) dienen. Einführung in das Programmieren 6/249 Einführung in das Programmieren 8/249 Was ist Java? Was ist Java? Das Erstellen eines Java - Programmes gliedert sich grob in drei wesentliche Schritte: Die folgende Liste enthält die für jeden Schritt wichtigen Programme: Quelltext schreiben Schritt Zu verwendendes Programm 1. Quelltext erstellen Jeder beliebige Editor, z.B. nedit 2. Bytecode erzeugen javac Quelltext.java 3. Bytecode interpretieren lassen java Quelltext Quelltext in Bytecode übersetzen Bytecode interpretieren lassen Einführung in das Programmieren 9/249 Einführung in das Programmieren 11/249 Was ist Java? Dabei ist der Quelltext die ”Handlungsanweisung”, die ”Schritt-für-Schritt” beschreibt, was der Computer genau erledigen soll. Linux und KDE in den Terminalräumen Der Bytecode ist ein sogenannter ”Zwischencode”. Der vom Menschen lesbare Quelltext wird in eine plattformneutrale Sprache übersetzt, die später vom Interpreter gelesen wird. Der Interpreter ist letztlich das Programm, das den Zwischencode in wirkliche Maschinenbefehle umsetzt. Einführung in das Programmieren 10/249 Einführung in das Programmieren 12/249 Linux und KDE in den Terminalräumen Linux und KDE in den Terminalräumen Im selben Anmeldungsfenster kann der Anwender zwischen mehreren sog. Fenstermanagern wählen. In den Terminalräumen läuft auf den meisten Rechnern als Betriebssystem Linux. Ein Fenstermanager dient der Verwaltung der auf einem graphischen System dargestellten Fenster. Als Voreinstellung wird KDE neben Gnome oder fvwm angeboten. Linux bezeichnet dabei nur den Teil des Betriebssystems, der sich um die Verwaltung und Verteilung von Ressourcen (wie z.B. Speicher) kümmert. Dieser Teil heißt Kernel. Für Umsteiger empfiehlt sich KDE, da es sich in der Bedienungsführung stark an Windows orientiert und dadurch sehr intuitiv zu bedienen ist. Um mit einem Computer jedoch sinnvoll arbeiten zu können, werden noch weitere Programme benötigt, beispielsweise eine Textverarbeitung. Die Gesamtheit aus Kernel und Anwendungsprogrammen wird Distribution genannt. Einführung in das Programmieren Wichtig ist, dass sich der Anwender nach abgeschlossener Arbeit vom Terminal abmeldet, damit die Arbeitsstation für andere Benutzer wieder freigegeben wird und kein Unfug mit der eigenen Benutzerkennung angestellt wird. 13/249 Linux und KDE in den Terminalräumen 15/249 Linux und KDE in den Terminalräumen Der Großteil der Arbeit dieses Praktikums wird in einer sog. Shell verrichtet. Sie ist vergleichbar mit der Eingabeaufforderung unter Windows, jedoch um Längen mächtiger. Linux unterscheidet sich in seiner Architektur grundlegend von dem populären Betriebssystem Windows. In einer Shell kann der Anwender direkt Befehle eintippen, die dann ausgeführt werden. Beispielsweise kann der Editor gestartet werden: Linux wurde bereits vom Design her auf ”Mehr-Benutzer-” (multi-user ) und ”Mehr-Programm-” (multi-tasking) Betrieb ausgelegt. Das wird sofort am Anmeldebildschirm (dem sog. Login-Screen) sichtbar: Die Anmeldung erfolgt mit der sog. y-Nummer. $ nedit & Das $-Zeichen ist der sog. Eingabeprompt. Die Shell signalisiert damit die Bereitschaft, dass Befehle angenommen und verarbeitet werden können. Diese Nummer muss, wenn noch nicht geschehen, im Rechenzentrum beantragt werden. Sie dient u.a. der Anmeldung und für den eMail-Verkehr. Einführung in das Programmieren Einführung in das Programmieren Das &-Zeichen dient dazu, dass der gestartete Editor von der umgebenden Shell gelöst wird. Damit kann in derselben Shell sofort der nächste Befehl eingegeben werden, ohne dass auf die Beendigung vom Editor nedit gewartet werden muss. 14/249 Einführung in das Programmieren 16/249 Linux und KDE in den Terminalräumen Linux und KDE in den Terminalräumen $ cd ABC Dieses Kommando wechselt in das Verzeichnis ABC. Die Shell arbeitet case sensitive. Damit sind $ nedit & $ cd und Dieses Kommando wechselt in das sog. Home-Directory des angemeldeten Anwenders. Das Home-Directory ist das Verzeichnis, in dem sich der Anwender unmittelbar nach dem Anmelden befindet. $ NEdit & zwei ganz unterschiedliche Befehle. Tipp: Durch Drücken der TAB-Taste versucht die Shell, den eingegebenen Befehl automatisch zu vervollständigen. Einführung in das Programmieren 17/249 Einführung in das Programmieren 19/249 Linux und KDE in den Terminalräumen Es folgen ein paar Befehle, um im ”Verzeichnisbaum” zu navigieren und die Shell kennen zu lernen. Weitere Befehle nebst Erläuterung befinden sich auf Aufgabenblatt 1. $ pwd Erste Schritte mit Java Dieses Kommando zeigt das momentane Arbeitsverzeichnis an. $ ls Dieses Kommando listet den Inhalt des aktuellen Verzeichnisses auf. Einführung in das Programmieren 18/249 Einführung in das Programmieren 20/249 Erste Schritte mit Java Erste Schritte mit Java Im folgenden soll ein Programm geschrieben werden, das einen beliebigen Text auf dem Bildschirm ausgeben soll: Jeder Quelltext in Java besteht wenigstens aus folgendem Block: 1 1 2 3 4 5 6 7 public class TextAusgabe { public static void main(String argv[]) { System.out.println("Textausgabe"); } } 2 3 4 1 2 public gehört zu den sog. Sichtbarkeitsoperatoren. Diese Operatoren sind unabdingbar für objektorientierte Programmierung. 21/249 Einführung in das Programmieren Erste Schritte mit Java Erste Schritte mit Java Jeder Quelltext in Java besteht wenigstens aus folgendem Block: Jeder Quelltext in Java besteht wenigstens aus folgendem Block: public class QuelltextName { 1 2 3 4 } class unterstreicht den objektorientierten Charakter von Java. Die meisten Quelltexte in Java sind Klassen. Auf die Objektorientierung wird später noch genauer eingegangen. Dieser Quelltext ist in einer Datei namens TextAusgabe.java zu speichern. Wichtig: Java ist ebenfalls case sensitive! Einführung in das Programmieren public class QuelltextName { 23/249 public class QuelltextName { 3 } 4 Dabei sind public und class sog. Schlüsselwörter. Schlüsselwörter dürfen nicht als Klassen-, Variablen- oder Funktionsnamen verwendet werden! Einführung in das Programmieren } Die geschweiften Klammern eröffnen und schließen einen Programmblock. Somit bedingt jede öffnende geschweifte Klammer auch eine schließende! 22/249 Einführung in das Programmieren 24/249 1 2 3 4 Erste Schritte mit Java Erste Schritte mit Java Jeder auszuführende Quelltext in Java besitzt darüber hinaus noch wenigstens folgenden Block: Die main - Funktion: 1 2 public class QuelltextName { public static void main(String argv[]) { 3 4 7 } } Einführung in das Programmieren 25/249 Einführung in das Programmieren Erste Schritte mit Java 2 3 4 27/249 Erste Schritte mit Java Jeder auszuführende Quelltext in Java besitzt darüber hinaus noch wenigstens folgenden Block: 1 } main ist der Name der Funktion. Nach der Java - Spezifikation muss die Einstiegsfunktion diesen Namen tragen. Andere Funktionen, die der Programmierer selbst definiert, können frei wählbare Namen besitzen. 5 6 public static void main(String argv[]) { Die main - Funktion: public class QuelltextName { public static void main(String argv[]) { 1 2 public static void main(String argv[]) { 3 4 } 5 } 6 7 public gehört wie bereits bei der Klasse zum objektorientierten Charakter von Java. Die main - Funktion muss immer die Sichtbarkeit public besitzen, sonst kann der entsprechende Quelltext nicht ausgeführt werden! } main lautet die Funktion, die vom Java - Interpreter als allererste Funktion aufgerufen wird. Dort ”steigt” der Java - Interpreter in den Quelltext ein. Einführung in das Programmieren 26/249 Einführung in das Programmieren 28/249 Erste Schritte mit Java Erste Schritte mit Java Die main - Funktion: Die main - Funktion: 1 2 1 public static void main(String argv[]) { 2 public static void main(String argv[]) { 3 3 4 4 } String ist ein Datentyp (genauer: Referenztyp). Ein Datentyp ist vergleichbar mit einer Menge in der Mathematik: Er beschreibt eine Menge von Elementen mit gleichen Eigenschaften. Beispielsweise beschreibt die Menge der natürlichen Zahlen und ein Element daraus. static ist ebenfalls ein Auszeichnungsmerkmal der Objektorientierung. Die main - Funktion muss immer das Schlüsselwort static besitzen, sonst kann der entsprechende Quelltext nicht ausgeführt werden! Einführung in das Programmieren } 29/249 Einführung in das Programmieren Erste Schritte mit Java 31/249 Erste Schritte mit Java Die main - Funktion: Die main - Funktion: 1 2 1 2 public static void main(String argv[]) { public static void main(String argv[]) { 3 4 } 3 4 } argv ist der Name eines Elements aus der o.a. Menge. Über diesen Namen wird das Element ”angesprochen”. Das bedeutet, über den Namen argv erhält man den Wert. Um das Beispiel von oben fortzusetzen: würde einer Zahl aus den natürlichen Zahlen entsprechen. String argv[ ] ist ein Argument. Auf Argumente werden in den Kapiteln ”Prozeduren” und ”Funktionen” näher eingegangen. Einführung in das Programmieren 30/249 Einführung in das Programmieren 32/249 Erste Schritte mit Java Erste Schritte mit Java Die main - Funktion: 1 Die main - Funktion: 2 1 2 public static void main(String argv[]) { public static void main(String argv[]) { 3 4 } 3 4 Wie bereits oben beschrieben, bezeichnet main den Funktionsnamen. In Java muss jede Funktion einen Rückgabewert besitzen. Ein Rückgabewert ist wieder die Bezeichnung einer Menge; beispielsweise kann String ein Rückgabewert sein. Wird allerdings kein Rückgabewert benötigt, schreibt man einfach void. Die main - Funktion muss immer den Rückgabewert void besitzen, sonst kann der entsprechende Quelltext nicht ausgeführt werden! } Die Klammern [ ] hinter argv bedeuten, dass mehrere Elemente vom Datentyp String definiert wurden. Auf die Verwendung von [ ] wird im Kapitel ”Felder” noch näher eingegangen. Einführung in das Programmieren 33/249 Einführung in das Programmieren 35/249 Erste Schritte mit Java Erste Schritte mit Java Wie oben bereits erläutert, ist String argv[ ] ein Argument. Es enthält die vom Anwender an das Programm übergebenen Werte. Ruft der Anwender das Programm beispielsweise wie folgt auf: Die erste Anweisung: System.out.println("Textausgabe"); 1 $ java QuelltextName Parameter1 Parameter2 Wie bereits erläutert, besteht ein Quelltext aus ”Handlungsanweisungen”. Die kürzeste Anweisung lautet ; . Darüber hinaus ist jede andere Anweisung (mit wenigen Ausnahmen) mit einem Semikolon abzuschließen. Dann enthält argv folgenden Wert: {"Parameter1", "Parameter2"}. Auf die Verwendung von Parametern und insbesondere von Feldern wird im Kapitel ”Fortgeschrittene Sprachkonzepte” eingegangen. Einführung in das Programmieren 34/249 Einführung in das Programmieren 36/249 Erste Schritte mit Java Die obige Anweisung gliedert sich in mehrere Teile. System.out. ist wieder eine Ausprägung der Objektorientierung. ”Turtle” - Programme mit den EIP classes println dagegen ist der Name einer Funktion, die zur Ausgabe von Text auf der Konsole (genauer: STDOUT) dient. "Textausgabe" ist der Parameter der Funktion println. Einführung in das Programmieren 37/249 Einführung in das Programmieren 39/249 ”Turtle” - Programme mit den EIP classes Erste Schritte mit Java Um aus dem Quelltext den benötigten Bytecode zu erzeugen, sind folgende Kommandos in der Shell auszuführen: $ javac TextAusgabe.java Für die Durchführung dieses Praktikums werden die sog. EIP classes zur Verfügung gestellt. Nachdem der Bytecode nun in einer .class-Datei vorliegt, kann er interpretiert werden: Die EIP classes sind bereits kompilierter Bytecode, in dem eine ganze Reihe von Funktionalitäten gesammelt wurden. $ java TextAusgabe Beispielsweise ist es mit den EIP classes möglich, eine gezeichnete Schildkröte über den Bildschirm laufen zu lassen. Letzlich erhält der Anwender folgende Ausgabe: Textausgabe Einführung in das Programmieren 38/249 Einführung in das Programmieren 40/249 1 ”Turtle” - Programme mit den EIP classes ”Turtle” - Programme mit den EIP classes Die EIP classes werden als .class-Dateien zur Verfügung gestellt. Damit sie in einem eigenen Programm verwendet werden können, muss im Quelltext auf das Paket eip verwiesen werden: Damit das o.a. Programm durch den Java Compiler übersetzt werden kann, muss der sog. CLASSPATH gesetzt werden. Der CLASSPATH enthält alle Verzeichnisse, die nach .class-Dateien während des Kompilier- und Interpretiervorgangs durchsucht werden müssen. import eip.*; 2 3 4 public class QuelltextName { Um das angegebene Programm zu übersetzen, muss wie folgt vorgegangen werden: 5 6 } $ javac -classpath /afs/common/tu-bs.de/eipclasses TextAusgabe.java Mittels import wird der Compiler angewiesen, das angegebene Paket bei der Erzeugung des Bytecodes mit zu verwenden. Einführung in das Programmieren 41/249 ”Turtle” - Programme mit den EIP classes Durch das vorangegangene Kommando wurde eine weitere .class-Datei erstellt. Sie liegt im sog. current working directory, also dem Verzeichnis, in dem sich der Anwender momentan befindet. import eip.*; 2 3 4 5 6 7 8 9 Um das Programm letztlich auszuführen, muss folgendes Kommando verwendet werden: public class QuelltextName { public static void main(String argv[]) { Std.out.println("Textausgabe"); } } Einführung in das Programmieren 43/249 ”Turtle” - Programme mit den EIP classes Das folgende Programm verwendet eine Funktion zur Textausgabe aus dem Paket der EIP classes: 1 Einführung in das Programmieren $ java -classpath /afs/common/tu-bs.de/eipclasses:. TextAusgabe Jetzt erhält man die bekannte Ausgabe: Textausgabe 42/249 Einführung in das Programmieren 44/249 ”Turtle” - Programme mit den EIP classes ”Turtle” - Programme mit den EIP classes Damit dem Java Compiler nicht jedes Mal über den Parameter -classpath mitgeteilt werden muss, wo sich die EIP classes und das eigene Programm befinden, kann man auch eine sog. Umgebungsvariable setzen. 1 import eip.*; 2 3 4 Eine Umgebungsvariable ist ein Parameter, der innerhalb der Shell eingerichtet wird. 5 6 Wenn der Java Compiler auf eine Umgebungsvariable namens $CLASSPATH trifft, werden alle dort enthaltenen Verzeichnisse während des Kompilierens und Interpretierens automatisch verwendet. 7 8 9 10 Gesetzt wird die Umgebungsvariable wie folgt: 11 public class TurtleSample { public static void main(String argv[]) { TurtleScreen ts = new TurtleScreen(); Turtle turtle = new Turtle(ts); turtle.fd(50); } } $ export CLASSPATH=/afs/common/tu-bs.de/eipclasses:. Einführung in das Programmieren 45/249 Einführung in das Programmieren ”Turtle” - Programme mit den EIP classes 47/249 ”Turtle” - Programme mit den EIP classes 1 import eip.*; 2 3 4 Im folgenden soll ein ”Turtle” - Programm geschrieben werden, das eine ”Schildkröte” anzeigt und um einen vordefinierten Weg nach vorne bewegt. 5 6 7 public class TurtleSample { public static void main(String argv[]) { ... Zu Beginn werden wieder die bekannten EIP classes eingebunden. In den EIP classes werden u.a. Funktionalitäten zur Darstellung einer ”Schildkröte” zur Verfügung gestellt. Einführung in das Programmieren 46/249 Einführung in das Programmieren 48/249 ”Turtle” - Programme mit den EIP classes ”Turtle” - Programme mit den EIP classes 1 1 ... 3 4 5 6 7 4 5 6 Einführung in das Programmieren 49/249 Einführung in das Programmieren ”Turtle” - Programme mit den EIP classes 51/249 ”Turtle” - Programme mit den EIP classes ... public static void main(String argv[]) { TurtleScreen ts = new TurtleScreen(); Turtle turtle = new Turtle(ts); turtle.fd(50); 2 3 4 5 6 7 ... Das neue Element ts wird nun als Parameter an eine neue Schildkröte weitergereicht. Damit wird in Zeile 5 der neuen Schildkröte die zu verwendende ”Leinwand” bekannt gegeben. Auf die genaue Verwendung des Schlüsselwortes new und die ”scheinbaren” Funktionen TurtleScreen() sowie Turtle(...) wird im Kapitel Objektorientierung genauer eingegangen. ... Die gesamte Funktion des kurzen Programmes ist in der main-Funktion implementiert. 1 public static void main(String argv[]) { TurtleScreen ts = new TurtleScreen(); Turtle turtle = new Turtle(ts); 3 public static void main(String argv[]) { TurtleScreen ts = new TurtleScreen(); Turtle turtle = new Turtle(ts); turtle.fd(50); 2 ... 2 1 turtle.fd(50); 2 } 3 4 ... } Die eigentliche Bewegung wird über die Anweisung turtle.fd(50); erreicht. Dabei bedeutet die Angabe 50, dass sich die virtuelle Schildkröte 50 Pixel auf dem Bildschirm Richtung Norden bewegen soll. Die .-Notation ist wiederum ein Merkmal der Objektorientierung. Zunächst wird vom Datentyp TurtleScreen ein neues Element mit dem Namen ts erzeugt. Das Schlüsselwort new ist dabei wiederum ein Merkmal der Objektorientierung; ebenso wie die scheinbare Funktion TurtleScreen(). Einführung in das Programmieren ... 50/249 Einführung in das Programmieren 52/249 ”Turtle” - Programme mit den EIP classes Um das erste ”Turtle”-Programm zu übersetzen, ist der folgende Befehl notwendig: $ javac -classpath /afs/common/tu-bs.de/eipclasses TurtleSample.java Fortgeschrittene Programmierkonzepte Um das Programm interpretieren zu lassen, wird wie folgt vorgegangen: $ java -classpath /afs/common/tu-bs.de/eipclasses:. TurtleSample Auf der folgenden Folie ist ein Bildschirmabzug des Programmes zu sehen. Einführung in das Programmieren 53/249 ”Turtle” - Programme mit den EIP classes Einführung in das Programmieren 55/249 Fortgeschrittene Programmierkonzepte Die nächsten Kapitel geben eine grundlegende Einführung in die fortgeschrittenen Programmierkonzepte von Java. Fortgeschrittene Programmierkonzepte erhöhen einerseits die Lesbarkeit von Programmen, andererseits dienen sie aber vielmehr der Schaffung von komplexen Programmen, die zur Bearbeitung von (komplizierten) Problemen dienen. Bildschirmabzug des ersten ”Turtle” - Programmes. Schwerpunktmässig werden Datentypen und Felder, Schleifen, Prozeduren und Funktionen, Objektorientierung und Applets erläutert. Der Aufbau hält sich an die Erfordernisse der einzelnen Hausaufgaben, so dass beispielsweise die for - Schleife zunächst gesondert betrachtet wird, bis anschließend mit den weiteren Schleifen die Wiederholungsstrukturen vervollständigt werden. Einführung in das Programmieren 54/249 Einführung in das Programmieren 56/249 Fortgeschrittene Programmierkonzepte Primitive Datentypen Im Unterschied zu anderen Programmiersprachen bietet Java bei Primitiven Datentypen den Vorteil, dass sog. Definite Assignment durchgeführt wird. Definite Assignment bedeutet einfach nur, dass Variablen einen definierten, gültigen Standardwert besitzen: Fortgeschrittene Programmierkonzepte Primitive Datentypen 1 ... int zahl1 = 10; int zahl2; 2 3 4 ... Der Variablen zahl1 wird der Wert 10 zugewiesen, wohingegen die Variable zahl2 auf den Standardwert 0 gesetzt wird. Einführung in das Programmieren 57/249 Fortgeschrittene Programmierkonzepte Primitive Datentypen Das vorangegangene Programmbeispiel illustriert bereits die Verwendung von Datentypen. Primitive Datentypen dienen allein dazu, einen konkreten Wert zu enthalten. Zwei Schritte sind notwendig, um einen Datentyp im Programm zu verwenden. Zunächst muss eine Variable des gewünschten Datentyps deklariert werden, bevor ihr anschließend ein Wert zugewiesen werden kann. Beispielsweise dient der Primitive Datentyp int dazu, ganze Zahlen ( ) zu speichern: int zahl; zahl = 24; 3 4 Namen (sog. Bezeichner) für Variablen, Funktionen usw. müssen mit einem Unicode-Buchstaben beginnen (”A” bis ”Z”, ”a” bis ”z”, ” ” und ”$” ) und können anschließend weitere Buchstaben oder Ziffern (keine Leerzeichen!) enthalten. ... 2 ... Einführung in das Programmieren 59/249 Fortgeschrittene Programmierkonzepte Primitive Datentypen In Java werden die Datentypen in Primitive Datentypen einerseits und Referenztypen andererseits unterschieden. 1 Einführung in das Programmieren 58/249 Einführung in das Programmieren 60/249 Wertebereich boolean false true, false 2 char \u0000 alle Unicode - Zeichen 3 byte 0 short 0 ... int 0 ... long 0 float 0.0f 5 ... double zahl1 = 20.0; int zahl2 = 30; zahl1 = zahl2; Die folgende Anweisung führt allerdings zu einem Fehler: 1 ... ... ... ... 4 ... 1 Standardwert Damit ist folgender Programmcode möglich: Primitiver Datentyp Folgende Primitive Datentypen kennt Java: Fortgeschrittene Programmierkonzepte Primitive Datentypen Fortgeschrittene Programmierkonzepte Primitive Datentypen zahl2 = zahl1; 0.0 ... double 2 Einführung in das Programmieren 3 61/249 ... Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Primitive Datentypen 63/249 Fortgeschrittene Programmierkonzepte Primitive Datentypen Der Compiler quittiert den zweiten Programmcode beispielsweise wie folgt: Von der Mathematik ist folgender Zusammenhang bekannt: 1 2 3 Für die Primitiven Datentypen gilt ein äquivalenter Zusammenhang: 4 5 byte short int long float double 6 7 8 Einführung in das Programmieren 62/249 $ javac Zuweisung.java Zuweisung.java:10: possible loss of precision found : double required: int zahl2 = zahl1; ˆ 1 error $ Einführung in das Programmieren 64/249 Fortgeschrittene Programmierkonzepte Primitive Datentypen Fortgeschrittene Programmierkonzepte Primitive Datentypen String name3, name4; name3 = new String("Meier"); name4 = new String("Meier"); System.out.println("Vergleich 2: " + (name3 == name4)); 7 8 Referenztypen enthalten, wie der Name bereits impliziert, eine Referenz auf einen konkreten Datentyp. Eine Referenz ist technisch betrachtet eine Speicheradresse, an der die konkreten Daten gefunden werden können. 9 10 11 12 ... Dadurch ergibt sich schon der wichtigste Unterschied: Wird das Programm übersetzt und ausgeführt, erhält der Anwender die folgende Ausgabe: Primitive Datentypen können miteinander verglichen werden, wohingegen Referenztypen nur über spezielle Funktionen verglichen werden können. Einführung in das Programmieren 1 2 3 4 5 6 $ java Vergleich Vergleich 1: true Vergleich 2: false 65/249 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Primitive Datentypen Fortgeschrittene Programmierkonzepte Primitive Datentypen Eine Sonderrolle nimmt der Datentyp String ein. Technisch betrachtet ist es ein Referenztyp, jedoch illustriert das folgende Programmbeispiel die Problematik: Wie bereits erläutert, ist String ein Referenztyp. Im ersten Teil des Programmtextes wird von Java nicht wie erwartet zweimal die Zeichenkette ”Meier” im Speicher abgelegt, um ressourcenschonend zu arbeiten. Somit erhalten die Variablen name1 und name2 diesselbe Referenz und der erste Vergleich liefert true. ... Im zweiten Teil wird explizit verlangt, dass die Zeichenkette ”Meier” zweimal im Speicher abgelegt wird. Somit enthalten name3 und name4 zwei unterschiedliche Referenzen und der Vergleich liefert false. String name1, name2; name1 = "Meier"; name2 = "Meier"; System.out.println("Vergleich 1: " + (name1 == name2)); Einführung in das Programmieren 67/249 Im Kapitel Referenztypen wird näher auf den Vergleich von Werten eines eingegangen. 66/249 Einführung in das Programmieren 68/249 Fortgeschrittene Programmierkonzepte Arithmetische Operatoren Arithmetische Bedeutung Bemerkung int a += 5; Für jeden vorangegangenen Operation Fortgeschrittene Programmierkonzepte Arithmetische Operatoren binären Operator möglich. b++; Erhöhung von b um 1 möglich. (Postinkrement). Auch für ++b; Erhöhung von b um 1 möglich. (Präinkrement). Auch für Einführung in das Programmieren 69/249 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Arithmetische Operatoren Fortgeschrittene Programmierkonzepte Arithmetische Operatoren Primitive Datentypen dienen jedoch nicht nur dazu, Werte zu speichern, sondern viel mehr, um mit ihnen zu rechnen. Zunächst scheinen die Prä- und Postinkrement-Operatoren keinen Unterschied aufzuwiesen. Der folgende Quelltext zeigt dennoch ihre verschiedenen Aufgaben: Folgende Tabelle listet die vorhandenen arithmetischen Operatoren auf: Bemerkung 2 int a = 5 + a; unär/binär 3 1 Arithmetische Operation Bedeutung int b = b - 7; unär/binär int c = 3 * b; binär 6 int d = d / 5; binär 7 int e = (20 % 6); binär ... int a, b = 6; a = b++; System.out.println("a=" + a + ", b=" + b); a = ++b; System.out.println("a=" + a + ", b=" + b); 4 5 71/249 ... (Divisionsrest) Einführung in das Programmieren 70/249 Einführung in das Programmieren 72/249 Fortgeschrittene Programmierkonzepte Arithmetische Operatoren Fortgeschrittene Programmierkonzepte Die for – Schleife Wenn der Programmausschnitt ausgeführt ist, erhält man folgende Ausgabe: 1 2 3 4 $ java Inkrement a=6, b=7 a=8, b=8 $ Schleifen werden eingesetzt, um eine oder mehrere Anweisungen mehrfach zu wiederholen. Der häufigste Fehler im Zusammenhang mit Schleifen ist eine fehlerhafte Struktur, die dann in einer sog. Endlosschleife endet. Der Postinkrement-Anweisung in Zeile 3 wird von Java also wie folgt interpretiert: ”Lese Wert von b. Weise diesen Wert a zu. Erhöhe b um 1.” Ein Programm, das sich in einer Endlosschleife ”verfangen” hat, kann nur noch mittels STRG + C abgebrochen werden. Die Präinkrement-Anweisung funktioniert dementsprechend genau umgekehrt. Einführung in das Programmieren 73/249 Einführung in das Programmieren 75/249 Fortgeschrittene Programmierkonzepte Die for – Schleife Die for – Schleife ist das flexibelste Schleifenkonstrukt, das Java kennt. Generell ist eine Schleife aus zwei Teilen aufgebaut: Einem Schleifenkopf und dem Schleifenkörper: Fortgeschrittene Programmierkonzepte Die for – Schleife 1 ... for(int i=0; i<10; i++) { System.out.println("Durchgang: " + i); } 2 3 4 5 6 Einführung in das Programmieren 74/249 ... Einführung in das Programmieren 76/249 Fortgeschrittene Programmierkonzepte Die for – Schleife Fortgeschrittene Programmierkonzepte Die for – Schleife for(init ; bedingung ; update) Der Schleifenkörper enthält die Anweisungen, die in jedem Schleifendurchlauf (Iteration) durchgeführt werden. bedingung ist der wichtigste Teil der for – Schleife. Die bedingung wird vor jedem Schleifendurchlauf geprüft und entscheidet letztendlich, ob ein weiterer Schleifendurchlauf stattfindet, oder ob die sog. Abbruchbedingung erreicht ist. Der Schleifenkopf ist das Kontrollkonstrukt eines Schleifenkörpers. Der Schleifenkopf einer for – Schleife ist aus drei Teilen aufgebaut: Im obigen Beispiel ist die Abbruchbedingung eingetreten, wenn die Schleifenvariable i einen Wert größer oder gleich 10 enthält. for(init ; bedingung ; update) Einführung in das Programmieren 77/249 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Die for – Schleife 79/249 Fortgeschrittene Programmierkonzepte Die for – Schleife for(init ; bedingung ; update) update wird nach jedem Schleifendurchlauf ausgeführt und dient meistens der Veränderung der Schleifenvariablen. for(init ; bedingung ; update) init wird genau einmal durchlaufen. In diesem Teil der for – Schleife werden meistens die sog. Zählvariablen initialisiert. Im obigen Beispiel wird nach jedem Schleifendurchlauf der Wert der Schleifenvariablen i um 1 erhöht. Denkbar sind aber auch andere Konstrukte, wie beispielsweise: Mehrere Zählvariablen werden durch Kommata getrennt. Eine Zählvariable, die im init-Bereich der for – Schleife deklariert wird, hat nur Gültigkeit innerhalb des Schleifenkörpers! 1 2 3 4 Einführung in das Programmieren 78/249 for(int i=0; i<10; i=i+2) { ... } Einführung in das Programmieren 80/249 1 2 3 4 1 2 3 4 Fortgeschrittene Programmierkonzepte Die for – Schleife Fortgeschrittene Programmierkonzepte Die for – Schleife Folgende Schleifenkonstrukte münden in einer Endlosschleife: Ausgabe auf der Konsole: for(;;) { ... } $ java Schleife1 i=0 i=1 i=2 $ java Schleife2 i=0 i=1 i=2 $ for(i = 0; i<10; i--) { ... } Einführung in das Programmieren 81/249 Einführung in das Programmieren 83/249 Fortgeschrittene Programmierkonzepte Die for – Schleife Die beiden folgenden Schleifenkonstrukte führen zur selben Ausgabe: 1 2 3 4 1 2 for(int i = 0; i<3; i++) { System.out.println("i=" + i); } Fortgeschrittene Programmierkonzepte Prozeduren for(int i = 0; i<3; System.out.println("i=" + i), i++); Jedoch läßt die Lesbarkeit bei der zweiten Variante sehr zu wünschen übrig. Einführung in das Programmieren 82/249 Einführung in das Programmieren 84/249 Fortgeschrittene Programmierkonzepte Prozeduren Fortgeschrittene Programmierkonzepte Prozeduren Der Funktionskörper enthält lediglich das ”Unterprogramm” (Anweisungen). Wie bereits unter ”Erste Schritte mit Java” angegeben, gibt es unter Java nur Funktionen. Funktionen sind grob gesehen ”Unterprogramme” des eigentlichen Programmes, die jeweils eine bestimmte Teilaufgabe zu bewältigen haben. Hingegen ist der Aufbau des Funktionskopfes komplizierter. Der Funktionskopf legt folgende Punkte fest: Funktionsname Funktionen benötigen immer einen Rückgabewert. Wie bereits erläutert, wird void verwendet, wenn kein Rückgabewert benötigt wird. Rückgabewert Parameterliste Funktionen, die keinen Rückgabewert benötigen und dadurch das Schlüsselwort void verwenden, heißen Prozeduren. Sichtbarkeit Lebensdauer Einführung in das Programmieren 85/249 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Prozeduren Fortgeschrittene Programmierkonzepte Prozeduren Wie bei den Schleifen sind auch Prozeduren/Funktionen nach einer festgelegten Struktur aufgebaut: Funktionsname 1 1 ... 2 void Prozedur() { ... } 2 3 4 5 6 3 Funktionsname() { .... Der Funktionsname ist ein Bezeichner für das ”Unterprogramm”, mit dem es später an anderer Stelle aufgerufen werden kann. Es gelten dieselben Regeln zur Bildung eines Namens wie für Variablennamen. Um eine Funktion zu kennzeichnen, werden dem Bezeichner () angehängt. ... Die Struktur gliedert sich in zwei Teile: Der Funktionskopf und der Funktionskörper. Einführung in das Programmieren 87/249 86/249 Einführung in das Programmieren 88/249 Fortgeschrittene Programmierkonzepte Prozeduren Fortgeschrittene Programmierkonzepte Prozeduren Parameterliste Parameterlisten sind vergleichbar mit Funktionsdefinitionen in der Mathematik: Rückgabewert 3 void Funktionsname() { .... ! " # " 2 1 Die erste Zeile stellt die Signatur einer Funktion dar. Die Funktion erwartet zwei natürliche Zahlen als Argumente. Der Rückgabewert einer Prozedur ist immer void. Die zweite Zeile beschreibt den ”Funktionskörper”. Die beiden Argumente werden addiert. Einführung in das Programmieren 89/249 Fortgeschrittene Programmierkonzepte Prozeduren 2 3 Parameterliste In Java könnte eine Parameterliste beispielsweise wie folgt aussehen: void Funktionsname(int x) { .... void Funktionsname(int x, int y) Die beiden Parameter bezeichnet man ebenfalls als Signatur der Funktion ”Funktionsname”. Das Auszeichnungsmerkmal einer Funktion, die angehängten (), enthalten in der Regel die Parameter, mit der eine Funktion aufgerufen wird. Wenn keine Parameter benötigt werden, bleibt die Liste leer. Die () dürfen jedoch nicht weggelassen werden! Einführung in das Programmieren 91/249 Fortgeschrittene Programmierkonzepte Prozeduren Parameterliste 1 Einführung in das Programmieren In Java gibt es das Konzept des Überladens. Überladen bedeutet, dass ein Funktionsname mehrfach verwendet werden kann, wenn sich die Signaturen unterscheiden. 90/249 Einführung in das Programmieren 92/249 Fortgeschrittene Programmierkonzepte Prozeduren Fortgeschrittene Programmierkonzepte Prozeduren Parameterliste Folgende Funktionen beispielsweise denkbar: 1 2 3 4 5 6 Sichtbarkeit void Funktionsname(int x, int y) { ... void Funktionsname(float x, float y) { ... public void Funktionsname(int x, int y) Sichtbarkeit ist ein Merkmal der Objektorientierung. Es existieren insgesamt vier Sichtbarkeitsoperatoren: public, protected, private und Default. Um Default zu verwenden, wird einfach keiner der anderen Sichtbarkeitsoperatoren angegeben. Sichtbarkeitsoperatoren dienen der Einschränkung des Zugriffs und wirken ausschließlich bei der objektorientierten Programmierung. Wird später im Quelltext die Funktion ”Funktionsname” aufgerufen, entscheidet Java anhand der übergebenen Parameter, welche der beiden Funktionen aufgerufen wird. Einführung in das Programmieren 93/249 Fortgeschrittene Programmierkonzepte Prozeduren Einführung in das Programmieren 95/249 Fortgeschrittene Programmierkonzepte Prozeduren Lebensdauer Parameterliste public static void Funktionsname(int x, int y) void Funktionsname(int x, int y) Das Schlüsselwort static wurde bereits im Kapitel ”Erste Schritte mit Java” erwähnt. Dort wurde es definitionsbedingt für die Funktion main benötigt. Die Signatur der Funktion ”Funktionsname” schreibt genau zwei Integer - Werte vor. Das bedeutet, dass die Funktion mit zwei Werten aufzurufen ist. Die Bezeichner x und y sind die Namen der Parameter, um innerhalb des Funktionskörpers auf die übergebenen Wert zugreifen zu können. Diese Bezeichner sind auch nur innerhalb des Funktionskörpers gültig. Einführung in das Programmieren static besagt, dass eine Funktion oder Variable nicht an die Lebensdauer eines bestimmten Objekts gebunden ist. Zu Beginn eines Java-Programmes existieren noch keine Objekte. Somit würde der Java-Interpreter die Funktion main nicht ”finden”, wenn sie das Schlüsselwort static nicht besäße. 94/249 Einführung in das Programmieren 96/249 Fortgeschrittene Programmierkonzepte Prozeduren Fortgeschrittene Programmierkonzepte Prozeduren 1 ... static int zahl = 10; static void Funktion1() { zahl = 20; Funktion2(); } static void Funktion2() { System.out.println("Zahl=" + zahl); } 2 3 4 Lebensdauer 5 public static void Funktionsname(int x, int y) 6 Wenn mit Java nicht objektorientiert programmiert wird, muss jede Funktion das Schlüsselwort static besitzen. Ansonsten kann sie nicht von einer anderen Funktion aus aufgerufen werden. 7 8 9 10 11 12 Einführung in das Programmieren 97/249 Fortgeschrittene Programmierkonzepte Prozeduren ... Einführung in das Programmieren 99/249 Fortgeschrittene Programmierkonzepte Prozeduren public static void Funktionsname(int x, int y) In Zeile 2 wird eine globale Variable mit dem Bezeichner zahl deklariert. Sie benötigt das Schlüsselwort static, damit ihre Lebensdauer nicht an ein bestimmtes Objekt gebunden ist und sie sofort verwendet werden kann. Somit ist der Funktionskopf vollständig. Allerdings gibt es noch einige Punkte zu beachten. Zunächst betrifft es die Verwendung von Variablen innerhalb von Funktionskörpern. Wird eine neue Variable innerhalb eines Funktionskörpers deklariert, ist sie auch nur dort gültig! Wird nun Funktion1() aufgerufen, wird zahl auf 20 gesetzt und anschließend Funktion2() aufgerufen. Dort wird der Inhalt der Variablen zahl auf der Konsole ausgegeben. Sollen zwischen zwei Prozeduren Werte ausgetauscht werden, kann man als einfachste Lösung globale Variablen verwenden. Einführung in das Programmieren 98/249 Einführung in das Programmieren 100/249 Fortgeschrittene Programmierkonzepte Prozeduren Der letzte Punkt, der bei der Verwendung von Prozeduren zu beachten ist, ist das sog. Scoping. Angenommen es existiert wie im vorangegangenen Beispiel eine globale Variable namens zahl. Fortgeschrittene Programmierkonzepte Funktionen Wenn nun innerhalb einer Funktion ebenfalls eine Variable mit dem Namen zahl deklariert wurde, verdeckt diese Variable die globale Variable, und man kann nur über einen Umweg auf den Wert der globalen Variablen zahl zugreifen. Das folgende Beispiel illustriert, wie man auf eine verdeckte globale Variable zugreifen kann. Einführung in das Programmieren 8 9 10 11 Einführung in das Programmieren Nun werden Funktionen betrachtet, die einen Rückgabewert erzeugen. Die folgende mathematische Funktion 7 Bisher wurden ausschließlich Funktionen betrachtet, die keinen Rückgabewert liefern (sog. Prozeduren). $& 6 public class Scoping { static int zahl = 10; void Funktion1() { int zahl = 20; System.out.println("Innen=" + zahl); System.out.println("Aussen=" + Scoping.zahl); } ... 5 Fortgeschrittene Programmierkonzepte Funktionen $ 4 Fortgeschrittene Programmierkonzepte Prozeduren 3 103/249 $% ! # 2 Einführung in das Programmieren $& 1 101/249 liefert die Summe zweier ganzer Zahlen zurück. Im folgenden wird diese Funktion in Java nachgebildet. 102/249 Einführung in das Programmieren 104/249 Fortgeschrittene Programmierkonzepte Funktionen int Summe(int z1, int z2) { int ergebnis = z1 + z2; return ergebnis; } 2 3 4 5 6 7 Der folgende Quelltext illustriert eine Funktion, die keine allgemein erreichbare return – Anweisung besitzt: ... 1 ... int Summe(int z1, int z2) { if (z1 == 0) { return z2; } } 2 3 4 ... 5 6 Da es sich bei dem abgebildeten Programmstück um eine Funktion und keine Prozedur handelt, liegt auch nicht mehr als Datentyp für den Rückgabewert void vor, sondern int. Einführung in das Programmieren 7 8 9 105/249 ... Einführung in das Programmieren 107/249 Fortgeschrittene Programmierkonzepte Funktionen Rückgabewerte von Funktionen können alle Datentypen sein: Primitive Datentypen Die genaue Verwendung des if – Statements wird im Kapitel ”Bedingungen” erläutert. Hier sei einmal vorgegriffen: Die Aufgabe des obigen Quelltextes ist es, im Fall von nur zurückzuliefern. Referenztypen Java quittiert den Quelltext wie folgt: Felder $ javac Addition.java Addition.java:10: missing return statement { ˆ 1 error $ $& $ Fortgeschrittene Programmierkonzepte Funktionen 1 Fortgeschrittene Programmierkonzepte Funktionen Die nächste wichtige Neuerung ist das Schlüsselwort return. Jede Funktion, die einen anderen Rückgabewert als void besitzt, muss eine allgemein erreichbare return – Anweisung besitzen. Einführung in das Programmieren 106/249 Einführung in das Programmieren 108/249 Fortgeschrittene Programmierkonzepte Funktionen Fortgeschrittene Programmierkonzepte Funktionen Darüber hinaus ist darauf zu achten, dass der Ausdruck, der über die return – Anweisung zurückgeliefert wird, kompatibel zum geforderten Rückgabewert ist. Java addiert beide Fließkommazahlen und wandelt das Ergebnis anschließend in eine ganze Zahl um, indem es den Nachkommaanteil abschneidet. Erinnerung: Im Kapitel ”Primitive Datentypen” wurden Obermengenbeziehungen festgelegt. Angenommen die obige Funktion besitze als Rückgabewert float. Werden nun allerdings zwei Werte des Datentyps int addiert, kann das Ergebnis trotzdem zurückgegeben werden, da float eine Obermenge von int ist. Die Möglichkeit, einen expliziten cast durchführen zu können, spielt bei der objektorientierten Programmierung eine wichtige Rolle. Java konvertiert das Ergebnis der Addition in einen Wert des Datentyps float. Diesen Vorgang bezeichnet man als impliziten cast, da er von Java automatisch durchgeführt wird. Einführung in das Programmieren Einführung in das Programmieren 111/249 Fortgeschrittene Programmierkonzepte Funktionen Fortgeschrittene Programmierkonzepte Funktionen In Java ist es auch möglich, einen sog. expliziten cast durchzuführen. Folgendes Programmstück illustriert diesen Vorgang: Eine weiteres wichtiges Anwendungsgebiet von Funktionen bildet die sog. Rekursion. ) ' 7 . ' ' - ... Einführung in das Programmieren )) 6 +,* ' ! ' # 5 4 ! '# 3 '( int Summe(float z1, float z2) { int ergebnis = (int) (z1 + z2); return ergebnis; } 2 Eine Rekursion liegt vor, wenn sich eine Funktion selbst wieder aufruft. Das bekannteste Beispiel für Rekursionen ist die Fakult äten . Funktion: ... 1 109/249 110/249 Einführung in das Programmieren 112/249 Fortgeschrittene Programmierkonzepte Funktionen Fortgeschrittene Programmierkonzepte Funktionen Im Vergleich mit Schleifen ist der häufigste Fehler bei Rekursionen eine fehlende Abbruchbedingung, die eine Rekursion zum Ende kommen lässt. Fehlt eine solche Bedingung, ”verfängt” sich die Funktion in einer Endlosschleife, und das Programm kann nur noch mittels STRG + C abgebrochen werden. Die Zeile 8 enthält die Anweisung, die in allen anderen Fällen ausgeführt wird. 113/249 Fortgeschrittene Programmierkonzepte Funktionen 4 5 6 7 8 9 : 0 Rekursive Berechnung von !# ( int fakultaet(int n) { if (n == 0) { return 1; } return n * fakultaet(n-1); } 3 10 Die Abarbeitung eines rekursiven Aufrufs kann man sich wie das Durchschreiten einer U-förmigen Treppe vorstellen: ... 2 115/249 Fortgeschrittene Programmierkonzepte Funktionen Der folgende Programmausschnitt implementiert die Fakultäten Funktion in Java: 1 Einführung in das Programmieren Einführung in das Programmieren ' ' / Die Abbruchbedingung ist in den Zeilen 4-7 implementiert. Damit ist , die Fakultäten – sichergestellt, dass für alle Argumente , mit Funktion mit einem sinnvollen Ergebnis terminiert. f(3) 6 3*f(2) 3*2*1*1 2*1*1 2*f(1) 1*1 1*f(0) 1 ... Einführung in das Programmieren 114/249 Einführung in das Programmieren 116/249 Fortgeschrittene Programmierkonzepte Funktionen Rekursionen sollten dann eingesetzt werden, wenn eine iterative Lösung nicht praktikabel erscheint. Beispielsweise ist das Türme von Hanoi – Problem rekursiv sehr schnell implementiert; eine iterative Implementierung ist wesentlich umfangreicher. Fortgeschrittene Programmierkonzepte Weitere Schleifen Der nächste Programmausschnitt stellt eine beispielhafte Implementierung dar. $ 1 ' Die verwendeten Parameter haben folgende Bedeutung: bezeichnet die Anzahl von Scheiben, ist die Nummer des Stapels, von dem die Scheiben umgelegt werden sollen, und bezeichnet den Zielstapel, wobei der Algorithmus für genau drei Stapel ausgelegt ist. Einführung in das Programmieren 117/249 Fortgeschrittene Programmierkonzepte Funktionen 1 2 3 4 5 6 7 8 9 10 11 12 119/249 Fortgeschrittene Programmierkonzepte Weitere Schleifen void hanoi(int n, int a, int z) { if (n > 1) { hanoi(n-1, a, (6 - a - z)); } System.out.println(a + " nach " + z); if (n > 1) { hanoi(n-1, (6 - a - z), z); } } Einführung in das Programmieren Einführung in das Programmieren Neben der bereits erläuterten for – Schleife gibt es noch zwei weitere Schleifenkonstrukte: Die while – Schleife und die do-while – Schleife. Der wesentliche Unterschied zwischen beiden und der for – Schleife ist der einfachere Aufbau des Schleifenkopfes. Während der Schleifenkopf der for – Schleife aus drei Teilen besteht, liegt bei diesen Schleifenkonstrukten nur der bedingung - Teil vor. 118/249 Einführung in das Programmieren 120/249 Fortgeschrittene Programmierkonzepte Weitere Schleifen Fortgeschrittene Programmierkonzepte Weitere Schleifen Beispiel für eine while – Schleife: 1 ... 3 4 5 6 7 8 Der Unterschied zwischen der kopf- und der fussgesteuerten Variante ist, dass der Schleifenkörper der letzteren auf jeden Fall einmal durchlaufen wird, da die Abbruchbedingung erst nach dem ersten Schleifendurchlauf geprüft wird. int i = 0; while (i < 10) { i++; System.out.println("Durchgang: " + i); } 2 Des weiteren ist zu beachten, dass eine Schleifenvariable außerhalb des Schleifenkonstruktes deklariert werden muss. Damit ist die Lebensdauer dieser Schleifenvariable auch nach Abarbeitung des Schleifenkonstruktes im Gegensatz zur for – Schleife nicht beendet. ... Die while – Schleife ist kopfgesteuert, da der bedingung - Teil vor jedem Schleifendurchlauf geprüft wird. Einführung in das Programmieren 121/249 Einführung in das Programmieren 123/249 Fortgeschrittene Programmierkonzepte Weitere Schleifen Beispiel für eine do-while – Schleife: 1 ... int i = 0; do { i++; System.out.println("Durchgang: " + i); } while (i < 10); 2 3 4 5 6 7 8 Fortgeschrittene Programmierkonzepte Relationale Operatoren ... Die do-while – Schleife ist fussgesteuert, da der bedingung - Teil erst nach jedem Schleifendurchlauf geprüft wird. Einführung in das Programmieren 122/249 Einführung in das Programmieren 124/249 Fortgeschrittene Programmierkonzepte Relationale Operatoren a == 5 gleich a != 5 ungleich 2 a < 5 echt kleiner 2 a <= 5 kleiner oder gleich a > 5 echt größer a >= 5 größer oder gleich Fortgeschrittene Programmierkonzepte Logische Operatoren ( Bedeutung . Relationale Operation Verwendung . Relationale Operatoren dienen dazu, Ausdrücke miteinander zu vergleichen und einen booleschen Rückgabewert zu erzeugen. Folgende relationale Operatoren kennt Java: Einführung in das Programmieren 125/249 Fortgeschrittene Programmierkonzepte Relationale Operatoren Einführung in das Programmieren 127/249 Fortgeschrittene Programmierkonzepte Logische Operatoren Logische Operatoren dienen dazu, boolesche Werte miteinander zu verbinden, um somit Wahrheitswerte weiterzuverarbeiten. Folgende logische Operatoren kennt Java: Wichtig: Der Gleichheitsoperator darf nicht mit dem Zuweisungsoperator verwechselt werden, da Java nicht auf diesen semantischen Fehler hinweisen kann! Folgende zwei Ausdrücke haben somit eine unterschiedliche Bedeutung: Verwendung Bedeutung (3 ( Logische Operation 54 4 3 4 4 logisches NICHT 5 66 logisches UND (Short-Circuit) 3 66 a = 5 Einführung in das Programmieren 126/249 Einführung in das Programmieren 75 3 logisches EXKLUSIVES ODER logisches UND 3 56 6 4 7 a == 5 54 3 logisches ODER (Short-Circuit) logisches ODER 128/249 Fortgeschrittene Programmierkonzepte Logische Operatoren Fortgeschrittene Programmierkonzepte Logische Operatoren Gesamtausdruck true true true true false false false true false false false false 4 Im Gegensatz zu den meisten anderen Programmiersprachen stellt Java die UND – und ODER – Verknüpfungen in zwei verschiedenen Varianten zur Verfügung: Einerseits mit und andererseits ohne sog. Short-Circuit-Evaluation. 54 Ausdruck 5 Ausdruck 3 3 Die Auswertung eines logischen Ausdrucks findet unter Verwendung von Wahrheitstabellen statt: Short-Circuit-Evaluation bedeutet, dass Teilausdrücke nur dann ausgewertet werden, wenn sie für das Gesamtergebnis noch Relevanz besitzen. Die o.a. Wahrheitstabelle enthält alle möglichen Wahrheitswerte der Teilausdrücke und den daraus resultierenden Wahrheitswert des Gesamtausdrucks. Einführung in das Programmieren 129/249 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Logische Operatoren Die folgende Tabelle wertet die logische Verknüpfung EXKLUSIVES ODER aus: Beispiel zur Short-Circuit-Evaluation: Gesamtausdruck 75 Ausdruck 5 Ausdruck 1 ... int a = 5; 3 3 Fortgeschrittene Programmierkonzepte Logische Operatoren 131/249 2 3 true true false true false true boolean b = (a > 7) && (a < 9); 4 false true true false false false 5 Da bereits der erste Teilausdruck false liefert, braucht der zweite Teilausdruck nicht mehr ausgewertet werden. Der Gesamtausdruck ist false, unabhängig vom Wahrheitswert des zweiten Teilausdrucks. Das logische EXKLUSIVE ODER ist genau dann true, wenn die beiden Teilausdrücke unterschiedliche Wahrheitswerte besitzen. Einführung in das Programmieren ... 130/249 Einführung in das Programmieren 132/249 Fortgeschrittene Programmierkonzepte Logische Operatoren Fortgeschrittene Programmierkonzepte Bedingungen Wahrheitswerte und logische Ausdrücke werden dazu verwendet, um den Programmfluss in Abhängigkeit einer Bedingung zu verzweigen. Der Verzicht auf die Short-Circuit-Evaluation setzt voraus, dass der gesamte logische Ausdruck ausgewertet werden kann. Das folgende Beispiel zeigt einen Gesamtausdruck, der ohne die Short-Circuit-Evaluation zwei Teilausdrücke verbindet: Im Kapitel ”Funktionen” wurde bereits auf eine einfache Verzweigung eingegangen: Das if – Konstrukt. Das if – Konstrukt prüft, ob der in Klammern stehende Ausdruck true ergibt. Wenn diese Bedingung erfüllt ist, wird der sich anschließende Programmblock ausgeführt: # 8 9 ( (a >= 0) && (a < 100) ) & ( fakultaet(a) > 0 ) 1 / 1 gilt, wird der Ausdruck zu true ausgewertet. Der Wenn Gesamtausdruck wird zu false ausgewertet, wenn gilt. Gilt , kann der Ausdruck nicht ausgewertet werden, da allerdings die Fakultäten – Funktion aus dem Kapitel ”Funktionen” für negative Parameter nicht terminiert. 1 2 1 Einführung in das Programmieren 2 3 4 133/249 if (a == 10) { System.out.println("a ist 10."); } Einführung in das Programmieren 135/249 Fortgeschrittene Programmierkonzepte Bedingungen Ein alternativer Programmblock, der genau dann ausgeführt wird, wenn der Ausdruck false liefert, kann über einen sog. else – Zweig angefügt werden: Fortgeschrittene Programmierkonzepte Bedingungen 1 2 3 4 5 6 7 8 Einführung in das Programmieren 134/249 if (a == 10) { System.out.println("a ist 10."); } else { System.out.println("a ist ungleich 10."); } Einführung in das Programmieren 136/249 Fortgeschrittene Programmierkonzepte Bedingungen Fortgeschrittene Programmierkonzepte Bedingungen Um den Gesamtausdruck nach mehreren Ergebnisse zu unterscheiden, wird das if – Konstrukt um einen oder mehrere else if – Zweige ergänzt: 1 2 3 1 ... 4 if (a == 10) { System.out.println("a ist 10."); } else if (a == 11) { System.out.println("a ist 11."); } 2 3 4 5 6 7 8 9 Einführung in das Programmieren 5 6 7 8 9 10 11 137/249 Fortgeschrittene Programmierkonzepte Bedingungen 11 13 15 Ein Fall beginnt immer mit case X:, wobei X einem Wert entspricht, und endet mit break; . Fehlt das break; , ist nicht gewährleistet, dass Java die Programmausführung mit der ersten Anweisung nach dem switch-case – Konstrukt fortsetzt. } 14 ... Diese Vorgehensweise ist bei überschaubaren Fallunterscheidungen praktibel. Steigt jedoch die Anzahl der Fallunterscheidungen an, bietet sich das folgende switch-case – Konstrukt eher an. Einführung in das Programmieren 139/249 Das switch-case – Konstrukt kann nur auf nummerische Datentypen, also byte, short, char oder int (kein long!), angewendet werden. System.out.println("a ist weder " + "10 noch 11."); 12 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Bedingungen else { 10 switch (a) { case 10: System.out.println("a ist 10"); break; case 11: System.out.println("a ist 11"); break; default: System.out.println("a ist weder 10 noch 11."); } Der default: – Fall entspricht dem else – Zweig und wird ausgeführt, wenn kein passender Fall gefunden werden konnte. 138/249 Einführung in das Programmieren 140/249 Fortgeschrittene Programmierkonzepte Bedingungen Fortgeschrittene Programmierkonzepte Bedingungen Wird für mehrere Fälle derselbe Programmblock ausgeführt, fasst man diese Fälle wie folgt zusammen: 1 2 3 4 5 6 7 8 9 10 switch (a) { case 10: case 11: System.out.println("a ist 10 oder 11."); break; default: System.out.println("a ist weder " + "10 noch 11."); } Einführung in das Programmieren 1 ... (A) ? B : C; 2 3 ... Dieser Operator kann nur innerhalb von Zuweisungen angewendet werden, und Ausdruck B und C müssen kompatibel zu dem Datentyp sein, dem sie zugewiesen werden. Der folgende Quellcode illustriert die Anwendung. 141/249 Einführung in das Programmieren Fortgeschrittene Programmierkonzepte Bedingungen 143/249 Fortgeschrittene Programmierkonzepte Bedingungen Das letzte Konstrukt zur Fallunterscheidung ist der sog. ? – Operator. Dieser Operator ist die Kurzform für: 1 3 4 5 6 7 8 9 ... int a = 10, b; 2 if (A) { B; } else { C; } 2 10 1 ... 3 b = (a > 5) ? 20 : 10; 4 5 ... Nach dieser Anweisung enthält b den Wert 20. Dieser sog. ternäre Operator kann auch geschachtelt werden, was allerdings nicht zur besseren Lesbarkeit des Quelltextes beiträgt! ... Einführung in das Programmieren 142/249 Einführung in das Programmieren 144/249 Fortgeschrittene Programmierkonzepte Felder Diese Vorgehensweise ist bei wenigen Variablen zwar einfach und schnell, jedoch verliert man bei steigender Anzahl von Variablen schnell die Übersicht. Um eine große Anzahl von Variablen zu bearbeiten, bietet sich das Konzept der Felder an. Ein Feld ist vergleichbar mit einem Regal mit -Fächern, in die ausschließlich Gegenstände gleicher Größe (des selben Typs) hineinpassen. Unter den Fächern ”klebt” zusätzlich noch die Fächernummer, deren Zählung bei beginnt: ' Fortgeschrittene Programmierkonzepte Felder 1 ... int zahlen[] = { 0, 89, 112, 21, -42, 23 }; 2 3 Einführung in das Programmieren 145/249 Einführung in das Programmieren Um auf die dritte Zahl ( ) zuzugreifen, muss das ”Regal” mit dem Namen zahlen und der Fächernummer angesprochen werden: Sollen mehrere Variablen eines gleichen Typs gespeichert werden, die eine semantische Zusammengehörigkeit aufweisen, könnte beispielsweise folgendes Programmstück verwendet werden: Fortgeschrittene Programmierkonzepte Felder ... 4 5 6 7 zahl0 zahl1 zahl2 zahl3 zahl4 zahl5 = = = = = = 0; 89; 112; 21; -42; 23; int zahlen[] = { 0, 89, 112, 21, -42, 23 }; 3 5 6 ... Bei der Verarbeitung von Feldern ist zu beachten, dass die Zählung endet! der Fächer bei beginnt und bei ' ... Einführung in das Programmieren System.out.println("Die dritte Zahl lautet: " + zahlen[2]); 4 3 ... 2 int int int int int int 2 8 147/249 Fortgeschrittene Programmierkonzepte Felder 1 1 ... 146/249 Einführung in das Programmieren 148/249 Fortgeschrittene Programmierkonzepte Felder Fortgeschrittene Programmierkonzepte Felder Bisher wurden lediglich eindimensionale Felder betrachtet. Es ist jedoch auch möglich, mehrdimensionale und asymmetrische Felder zu erzeugen. 1 : : Ein weiterer Vorteil von Felder ist die dynamische Festlegung der Größe eines Feldes zur Laufzeit. Folgender Quellcodeausschnitt , wobei statt zeigt die Erzeugung eines Feldes der Größe durchaus auch eine (int-kompatible) Variable verwendet werden kann: Um ein mehrdimensionales, symmetrisches Feld zu erzeugen, wird für jede benötigte Dimension ein Klammernpaar [ ] bei der Variablendeklaration angehängt: ... int zahlen[]; 2 int zahlenmatrix[][]; 1 3 5 Die Zuweisung der erfordlichen Größe gestaltet sich nun wie folgt: zahlen = new int[500]; 4 ... zahlenmatrix = new int[5][5]; 1 Einführung in das Programmieren 149/249 Einführung in das Programmieren 151/249 Fortgeschrittene Programmierkonzepte Felder Um ein Feld zu erzeugen, wird zunächst eine Variable vom gewünschten Datentyp mit angehängten eckigen Klammern [ ] deklariert: Nun enthält das Feld zahlenmatrix eine -Matrix. Auf die einzelnen Elemente wird nun wie gewohnt zugegriffen: : : Fortgeschrittene Programmierkonzepte Felder 1 1 int zahlen[]; ... int zahlenmatrix[][]; zahlenmatrix = new int[5][5]; 2 3 Anschließend muss diesem leeren Feld durch den Operator new gefolgt vom entsprechenden Datentyp die erforderliche Größe zugewiesen werden: 4 zahlenmatrix[2][4] = 12; System.out.println("Eintrag (3,5)=" + zahlenmatrix[2][4]); 5 6 7 1 zahlen = new int[500]; Einführung in das Programmieren 8 150/249 ... Einführung in das Programmieren 152/249 1 2 3 4 5 6 Fortgeschrittene Programmierkonzepte Felder Um ein mehrdimensionales, asymmetrisches Feld zu erzeugen, wird ebenfalls für jede benötigte Dimension ein Klammernpaar [ ] bei der Variablendeklaration angehängt. Die Zuweisung der erfordlichen Größe gestaltet allerdings umständlicher: Die Anweisung in Zeile 3 liefert die Größe der ersten Dimension zurück (in diesem Fall ). Die Anweisung in Zeile 5 liefert die Größe der zweiten Dimension der letzten Zeile zurück (hier ). : Fortgeschrittene Programmierkonzepte Felder Da ein mehrdimensionales, symmetrisches Feld vorliegt, ist die zweite Dimension jeder Zeile gleich groß. int zahlenmatrix[][]; zahlenmatrix = new int[5][]; for (int i=0; i<5; i++) { zahlenmatrix[i] = new int[i + 1]; } Einführung in das Programmieren Der Operator spielt also bei asymmetrischen Feldern oder Feldern, deren Größe erst während der Laufzeit durch eine (int-kompatible) Variable festgelegt wurde, eine wichtige Rolle. 153/249 Einführung in das Programmieren 155/249 Fortgeschrittene Programmierkonzepte Felder Der vorangegangene Programmausschnitt erzeugt ein dreieckiges Feld, dessen erste Zeile einen Eintrag enthält, dessen zweite Zeile zwei Einträge usw. enthält. Der letzte wichtige Punkt im Zusammenhang mit Feldern ist die .length - Eigenschaft. Jedes Feld besitzt für jede Dimension ein Attribut mit dem Namen .length, das dessen Größe zurückliefert: 1 2 3 4 5 Endliche Automaten int zahlen[][] = new int[5][20]; System.out.println("Groesse des Feldes" + zahlen.length); System.out.println("Groesse der 5. Zeile" + zahlen[4].length); Einführung in das Programmieren 154/249 Einführung in das Programmieren 156/249 Endliche Automaten Endliche Automaten Endlichen Automaten werden zur eindeutigen und vollständigen Beschreibung einer endlichen Anzahl von Zustandsveränderungen verwendet. Die graphische Darstellung des obigen endlichen Automaten stellt die Überprüfung der Zeichenkette in kürzerer Form dar: Beispielsweise kann man einen endlichen Automaten erstellen, der eine gegebene Zeichenkette dahingehend überprüft, ob sie mit der Zeichenfolge ”aa” beginnt, mit ”ab” endet und dazwischen kein oder beliebig viele Zeichen ”b” enthält. Folgende Zeichenketten sind somit gültig: a S=q 1 a q 2 a q 3 b q 4 q =A 5 b aaab aabab aabbbab Einführung in das Programmieren 157/249 Einführung in das Programmieren Endliche Automaten 159/249 Endliche Automaten Der endliche Automat lässt sich nun wie folgt in Java umsetzen: 1 Tabellarisch lässt sich der endliche Automat wie folgt beschreiben: 2 Zeichen ”a” Zeichen ”b” 3 4 &< – 5 – < &< < ; Zustand < <= < 6 8 9 3 <= – < 3 7 den Anfangszustand und ; Hierbei bezeichnet den Endzustand. 10 11 Einführung in das Programmieren 158/249 public class EndlicherAutomat { public static void main(String argv[]) { if (argv.length != 1) { System.out.println("Es wurde keine " + "Zeichenkette angegeben."); System.exit(0); } String s = argv[0]; Einführung in das Programmieren 160/249 Endliche Automaten Endliche Automaten // Zustand q3. int i = 2; while ((s.length() - 2) > i) { if (s.charAt(i) != ’b’) { System.out.println("Zeichenkette " + "ungueltig."); System.exit(0); } i++; } 28 29 // Zustand S=q1. if ( (s.length() < 1) || (s.charAt(0) != ’a’) ) { System.out.println("Zeichenkette " + "ungueltig."); System.exit(0); } 12 13 14 15 16 17 18 19 30 31 32 33 34 35 36 37 38 39 Einführung in das Programmieren 161/249 Einführung in das Programmieren Endliche Automaten 20 21 22 23 24 25 26 27 Einführung in das Programmieren 163/249 Endliche Automaten // Zustand q2. if ( (s.length() < 2) || (s.charAt(1) != ’a’) ) { System.out.println("Zeichenkette " + "ungueltig."); System.exit(0); } 40 41 42 43 44 45 46 47 162/249 Einführung in das Programmieren // Zustand q4. if ( ((s.length() - 1) < i) || (s.charAt(i) != ’a’) ) { System.out.println("Zeichenkette " + "ungueltig."); System.exit(0); } 164/249 Endliche Automaten // Zustand q5=A. i++; if ( (s.length() < i) || (s.charAt(i) != ’b’) ) { System.out.println("Zeichenkette " + "ungueltig."); System.exit(0); } System.out.println("Zeichenkette " + "gueltig."); 48 49 50 51 52 53 54 55 56 57 58 Eine Ausführung des Programmes könnte wie folgt aussehen: $ javac EndlicherAutomat.java $ java EndlicherAutomat Es wurde keine Zeichenkette angegeben. $ java EndlicherAutomat aaab Zeichenkette gueltig. $ java EndlicherAutomat aabab Zeichenkette gueltig. $ java EndlicherAutomat aabbbab Zeichenkette gueltig. $ java EndlicherAutomat aabbabbab Zeichenkette ungueltig. } 59 60 Endliche Automaten } Einführung in das Programmieren 165/249 Einführung in das Programmieren 167/249 Endliche Automaten Anmerkung: Ein String wird als eine Folge von Zeichen betrachtet. Im Kapitel ”Felder” wurde der Vergleich mit einem Regal, das nummerierte Fächer enthält, gezogen. Überträgt man nun dieses Bild auf eine Zeichenfolge, so besitzt das erste Zeichen die Nummer , das letzte , wobei die Anzahl der Zeichen in einer Zeichenkette Zeichen bezeichnet. ' ' Referenztypen Die folgende Anweisung s.charAt(2); liefert also das dritte Zeichen der Zeichenkette s. Die technischen Einzelheiten werden im Kapitel ”Objektorientierung” erklärt. Einführung in das Programmieren 166/249 Einführung in das Programmieren 168/249 Referenztypen Referenztypen Referenztypen müssen verwendet werden, um mit Java objektorientiert zu programmieren. Sie sind somit ein wesentliches Merkmal der Objektorientierung. Sie unterscheiden sich von den Primitiven Datentypen dadurch, dass sie nur indirekt einen ”Wert” enthalten. In Zeile 1 wird lediglich die ”Hülle” einer Variablen angelegt. In der folgenden Anweisung wird dieser ”Hülle” eine gültige Referenz zugewiesen. Die beiden Anweisung können auch zusammengefasst werden: 1 Vielmehr enthalten Referenztypen nur die Adresse (die Speicherstelle), an der sich die eigentlichen Daten befinden. Im Gegensatz zu anderen Programmiersprachen muss die mittels new angeforderte Speicherstelle nicht explizit freigegeben werden. Während der Programmausführung arbeitet im Hintergrund ein sog. garbage collector, der unerreichbare Speicherstellen freigibt. Zwar bietet Java Typensicherheit, jedoch erfordern Referenztypen einen höheren Aufwand und größere Aufmerksamkeit bei der Verwendung als Primitive Datentypen, da sie eine höhere Flexibilität aufweisen, die schnell zu Fehlern führen kann. Einführung in das Programmieren 169/249 Referenztypen String name; name = new String(); Ein weiteres Merkmal von Referenztypen ist die Möglichkeit, dass mehrere Referenzen auf diesselbe Speicherstelle zeigen können. Die ”Funktion” hinter dem Schlüsselwort new wird Konstruktor bezeichnet und im nächsten Kapitel ”Objektorientierung” näher erläutert. Einführung in das Programmieren 171/249 Eine Speicherstelle ist beispielsweise unerreichbar, wenn die auf sie zeigende Referenz ungültig wird. Eine Referenz ist ungültig, wenn ihr die sog. null-Referenz zugewiesen wird. Damit ist die Speicherstelle, die der Referenz zugeordnet wurde, nicht mehr ansprechbar. 2 3 Einführung in das Programmieren Referenztypen Referenztypen können ausschließlich von Klassen erzeugt werden. Im Kapitel ”Primitive Datentypen” wurde bereits die Klasse String vorgestellt. Eine Variable einer Klasse wird wie folgt deklariert und Objekt (oder auch Instanz) bezeichnet: 1 String name = new String(); 170/249 Einführung in das Programmieren 172/249 Referenztypen 1 String name1 = new String("Meier"); 2 3 String name2 = new String("Schulz"); Objektorientierung 4 5 name1 = name2; Zunächst wird der Referenz name1 die Speicherstelle mit dem Inhalt ”Meier” zugewiesen. Einführung in das Programmieren 173/249 Einführung in das Programmieren Referenztypen Objektorientierung Anschließend wird eine neue Referenz name2 erzeugt, die auf eine andere Speicherstelle mit dem Inhalt ”Schulz” verweist. Bisher wurde in diesem Workshop ausschließlich imperativ programmiert. Das bedeutet, es wurde dem java - Interpreter Schritt für Schritt vorgeschrieben, was zu tun ist. Die letzte Anweisung in Zeile 5 schließlich ordnet der Referenz name1 diesselbe Speicherstelle zu, auf die auch die Referenz name2 ”zeigt”. Objektorientiert zu programmieren bedeutet, eine andere Sichtweise auf das Ausgangsproblem anzuwenden. Bislang wurden u.a. Sichtbarkeitsoperatoren oder auch Referenzen als Merkmale der Objektorientierung ausgemacht. Während der Laufzeit stellt nun der garbage collector fest, dass die Speicherstelle mit dem Inhalt ”Meier” nicht mehr erreichbar ist und gibt sie wieder frei. Einführung in das Programmieren 175/249 Den wesentlichen Kern bilden aber Objekte, die miteinander in Beziehung und Kommunikation stehen. 174/249 Einführung in das Programmieren 176/249 Objektorientierung Objektorientierung Ein Objekt ist eine konkrete und einmalige Ausprägung einer Klasse (vgl. Schlüsselwort class). Eine Klasse fasst Eigenschaften, Fähigkeiten und die ”Bauanleitung” für ein Objekt zusammen. Aufbau einer Klasse - Struktur : 1 2 Als Eigenschaften (auch Attribute genannt) werden alle nicht-lokalen Variablen einer Klasse bezeichnet. Lokale Variablen sind beispielsweise Variablen, die innerhalb einer Funktion deklariert werden. 3 4 Eine Klasse wird immer über das Schlüsselwort class eingeleitet. Es ist möglich, mehrere Klassen in einer Quellcode-Datei zusammenzufassen, jedoch wird hier ausdrücklich davon abgeraten, da die Lesbarkeit und Übersichtlichkeit darunter leidet. Die Fähigkeiten einer Klasse bilden die Funktionen (in der Objektorientierung Methoden genannt). Der Konstruktor einer Klasse ist die ”Bauanleitung” eines Objektes. Einführung in das Programmieren class Name { ... } 177/249 Einführung in das Programmieren Objektorientierung 179/249 Objektorientierung Schematisch gliedert sich eine Klasse wie folgt: Aufbau einer Klasse - Struktur : 1 2 3 4 5 6 7 8 9 10 11 12 class Name { // Attribute: int zahl1; String str; // Konstruktor: Name() {} // Methoden: void ausgeben() {} } Einführung in das Programmieren 1 2 3 4 public class Name { ... } Dem Schlüsselwort class kann noch einer der folgenden Sichtbarkeitsoperatoren vorangestellt werden: public, protected oder private. Die Sichtbarkeitsoperatoren spielen eine wichtige Rolle bei Vererbungshierarchien von Klassen. Innerhalb dieses Workshops wird ausschließlich das Schlüsselwort public verwendet. 178/249 Einführung in das Programmieren 180/249 1 2 3 4 5 Objektorientierung Objektorientierung Aufbau einer Klasse - Attribute: Aufbau einer Klasse - Attribute: public class Name { int zahl; String str; ... 1 2 3 4 Als weiteres besonderes Schlüsselwort kann final für Attribute verwendet werden. Variablen, die mit final ausgezeichnet werden, lassen sich während der Laufzeit nicht mehr verändern. Solche Variablen werden als Konstanten bezeichnet. Die Reihenfolge von Attributen, Konstruktoren und Methoden innerhalb einer Klasse ist beliebig, jedoch wird hier die Ordnung der schematischen Darstellung von Folie 178 empfohlen. Einführung in das Programmieren 181/249 Einführung in das Programmieren Objektorientierung 2 3 4 5 Aufbau einer Klasse - Attribute: public class Name { int zahl; public String str; ... 1 2 3 4 public class Name { static int zahl = 10; ... Im Kapitel ”Prozeduren” (Folie 99) wurde bereits auf das Schlüsselwort static eingegangen. Mit static ausgezeichnete Variablen (oder auch Methoden) sind nicht an die Lebensdauer eines Objekts gebunden. Solche Variablen bezeichnet man als Klassenvariablen. Als Attribute einer Klasse sind Primitive Datentypen, Felder und Referenztypen zulässig. Attribute können über dieselben Sichtbarkeitsoperatoren wie Klassen beeinflusst werden. Bei Attributen schränken sie den Zugriff auf die eigenen Variablen für andere Objekte ein. Einführung in das Programmieren 183/249 Objektorientierung Aufbau einer Klasse - Attribute: 1 public class Name { final float PI = 3.14159; ... 182/249 Einführung in das Programmieren 184/249 Objektorientierung Objektorientierung Aufbau einer Klasse - Methoden: Aufbau einer Klasse - Konstruktor : 1 2 3 4 5 6 public class Name { ... void ausgeben() { System.out.println("Hallo Welt"); } ... 1 2 3 4 5 6 Methoden einer Klasse werden genauso behandelt wie Funktionen und Prozeduren. Stellt man dem Methodenkopf das Schlüsselwort static voran, ist die Methode nicht an die Lebensdauer eines Objekts gebunden. Eine solche Methode bezeichnet man als Klassenmethode. Eine bereits bekannte Klassenmethode ist die Prozedur main. Einführung in das Programmieren 1 2 3 4 5 7 public class Name { ... Name() { zahl = 0; } ... Im Funktionskörper des Konstruktors sollten Aufgaben erledigt werden, um ein gültiges Objekt zu erzeugen. Beispielsweise könnten Variablen und Datenstrukturen initialisiert werden. 185/249 Einführung in das Programmieren Objektorientierung Objektorientierung Aufbau einer Klasse - Konstruktor : Aufbau einer Klasse - Konstruktor : public class Name { ... Name() {} ... 1 2 3 4 5 6 Ein Konstruktor ist eine spezielle Funktion einer Klasse. Der Name dieser Funktion muss identisch sein mit dem Klassenname. Der Konstruktor wird als erste Funktion aufgerufen, sobald ein neues Objekt dieser Klasse erzeugt wird. Ein Konstruktor besitzt keinen Rückgabewert; vielmehr liefert er die zugehörige, aufbereitete Speicherstelle an eine Referenz zurück. Einführung in das Programmieren 7 187/249 public class Name { ... Name() {} Name(String s) {} ... Darüber hinaus dürfen Konstruktoren wie Funktionen und Prozeduren überladen werden (vgl. Folie 92), wenn sie unterschiedliche Signaturen besitzen. Ein Konstruktor ohne Argumentenliste (Zeile 3) wird als Standardkonstruktor bezeichnet. 186/249 Einführung in das Programmieren 188/249 Objektorientierung Objektorientierung Um von einer Klasse ein konkretes Objekt (auch Instanz genannt) zu erzeugen, wird der Operator new verwendet: Am Anfang jedes Java-Programmes existieren noch keine Objekte, die miteinander kommunizieren können. Der Einstiegspunkt für den Java-Interpreter ist die bereits erwähnte main - Funktion. Name name1, name2; 1 Da die main - Funktion das Schlüsselwort static besitzen muss, ist sie nicht an die Lebensdauer eines konkreten Objekts gebunden, sondern kann durch den Interpreter aufgerufen werden. 2 name1 = new Name(); name2 = new Name("Schulz"); 3 4 Bislang wurde imperativ programmiert. Daher waren alle Funktionen, Prozeduren und globalen Variablen mit static ausgezeichnet. Die imperative Programmierung bildet somit eine Teilmenge der objektorientierten Programmierung. In Zeile 1 werden zwei Objekte vom Referenztyp Name deklariert. In Zeile 3 wird für name1 durch den Operator new eine Speicherstelle angefordert. Diese Speicherstelle wird durch den Standardkonstruktor gefüllt. In Zeile 4 hingegen wird der zweite Konstruktor verwendet, da der Parameter "Schulz" übergeben wurde. Einführung in das Programmieren 1 Im folgenden wird eine kleine Adressverwaltung objektorientiert programmiert. 189/249 Objektorientierung Objektorientierung Auf die Attribute und Methoden eines Objekts wird mittels Punkt-Notation zugegriffen: Zunächst stelle man sich einen Karteikasten vor, in dem auf jeder Karteikarte eine Adresse steht. Zur Vereinfachung nehme man an, dass der Karteikasten genau zehn Karteikarten enthält. ... 2 Name name1; Als Objekte kann man nun den Karteikasten und eine Karteikarte ausmachen. name1 = new Name(); Auf der Karteikarte soll immer genau eine Adresse enthalten sein. Die Adresse bestehe aus dem Vor- und Nachnamen, einer Anschrift und einer eMail-Adresse. 3 4 5 name1.tuDies(); name1.zahl = 20; 6 7 8 Einführung in das Programmieren Da der Karteikasten genau zehn Karteikarten enthalten soll, bietet sich ein Feld als Datenstruktur an. ... Einführung in das Programmieren 191/249 190/249 Einführung in das Programmieren 192/249 Objektorientierung Objektorientierung ... this.PLZ = PLZ; this.Ort = Ort; this.eMail = eMail; 20 21 1 2 3 4 5 6 7 8 public class Karteikarte { // Attribute: String Name = "", Vorname = ""; String Strasse = "", Hausnummer = ""; String PLZ = "", Ort = ""; String eMail = ""; ... Einführung in das Programmieren 22 23 24 25 Die Argumentenliste des Konstruktors enthält Variablen, die dieselben Namen wie die Attribute tragen. Ihre Sichtbarkeit (sog. scoping, vgl. Folie 101) ist nur innerhalb des Konstruktors gegeben. Um nun eine gleichlautende Variable der Argumentenliste von einem Attribut zu unterscheiden, wird das Schlüsselwort this verwendet. 193/249 Objektorientierung 9 10 11 12 13 14 15 16 17 18 19 Einführung in das Programmieren 195/249 Objektorientierung ... // Konstruktor: Karteikarte(String Name, String Vorname, String Strasse, String Hausnummer, String PLZ, String Ort, String eMail) { this.Name = Name; this.Vorname = Vorname; this.Strasse = Strasse; this.Hausnummer = Hausnummer; ... Einführung in das Programmieren } ... this ist eine Referenz auf das Objekt, das gerade bearbeitet wird. Da this im Konstruktor der Klasse Karteikarte verwendet ist, beschreibt this die Referenz, der die augenblicklich angeforderte Speicherstelle zugeordnet wird. Somit beschreibt this.PLZ der Zeile 21 das Attribut PLZ einer neuen Referenz, dem der Wert PLZ aus der Parameterliste des Konstruktors zugewiesen wird. 194/249 Einführung in das Programmieren 196/249 Objektorientierung Objektorientierung 1 ... // Methode: public void ausgeben() { System.out.println(Name+", "+Vorname+"\n" +Strasse+" "+Hausnummer+"\n" +PLZ+" "+Ort+"\n" +eMail); } 26 27 28 29 30 31 32 33 34 35 2 3 4 5 6 7 8 9 10 } 11 12 Einführung in das Programmieren 197/249 Objektorientierung public class Karteikasten { public static void main(String argv[]) { Karteikarte karten[] = new Karteikarte[10]; karten[0] = new Karteikarte("Mustermann", "Michael", "Musterstrasse", "5a", "12345", "Musterhausen", "[email protected]"); ... } } Einführung in das Programmieren 199/249 Objektorientierung Ein weiteres wichtiges Merkmal der Objektorientierung ist die Möglichkeit der Vererbung. Damit ist die Klasse für ein Objekt ”Karteikarte” erstellt. Vererbung bedeutet, dass eine Klasse die Attribute und Methoden einer anderen Klasse übernimmt und (häufig) ergänzt. Da der Karteikasten als Feld implementiert werden soll, bietet sich beispielsweise die main - Funktion an. Anschaulich bedeutet es, dass man beispielsweise eine Klasse PKW erstellt hat. Später stellt sich heraus, dass noch zwei weitere Objekte, nämlich ein Polizeiwagen und ein Rettungswagen, abgebildet werden sollen. Besäße der Karteikasten keine fixierte Anzahl von Karteikarten, würde man eine spezielle Klasse Karteikasten erstellen, die Methoden zum Einfügen und Entfernen von Karteikarten enthielte. Eine solche Klasse könnte auch die Funktionalität zum Sortieren der Karteikarten bereitstellen. Einführung in das Programmieren Es wäre nun unsinnig, für die Klassen Einsatzwagen nochmal alle Attribute und Methoden des Klasse PKW zu implementieren, da diese Eigenschaften und Fähigkeiten gleich sind. 198/249 Einführung in das Programmieren 200/249 Objektorientierung Objektorientierung Das folgende UML-Diagramm veranschaulicht die Vererbung: PKW ... // Konstruktor: PKW(float Geschwindigkeit, float Gewicht, String Kennzeichen) { this.Geschwindigkeit = Geschwindigkeit; this.Gewicht = Gewicht; this.Kennzeichen = Kennzeichen; } ... 9 +Geschwindigkeit: float +Gewicht: float +Kennzeichen: String +ausgeben(): void 10 11 12 13 14 Einsatzwagen +Dienststelle: String +ausgeben(): void 15 Die Methode ausgeben() erscheint trotz Vererbung erneut in der abgeleiteten Klasse Einsatzwagen, da sie dort einen anderen Funktionskörper enthält. Eine solches Merkmal bezeichnet man als Überschreiben. 17 Einführung in das Programmieren 16 18 201/249 Einführung in das Programmieren Objektorientierung Objektorientierung Ein mögliche Implementierung für die Klasse PKW wäre z.B. folgende: ... // Methoden: void ausgeben() { System.out.println("Geschwindigkeit " + Geschwindigkeit + ", Gewicht " + Gewicht + ", " + Kennzeichen); } 19 1 2 3 4 5 public class PKW { // Attribute: float Geschwindigkeit; float Gewicht; 20 21 22 23 24 25 6 7 8 String Kennzeichen = ""; ... Einführung in das Programmieren 203/249 26 27 202/249 } Einführung in das Programmieren 204/249 Objektorientierung Objektorientierung Eine mögliche Implementierung für die Klasse Einsatzwagen wäre z.B. folgende: 1 2 3 4 5 6 7 8 9 10 Da bei Erzeugung eines Objekts der Klasse Einsatzwagen zunächst der Standardkonstruktor der Vaterklasse PKW aufgerufen wird, muss die Klasse PKW noch um diesen Konstruktor ergänzt werden, sonst erzeugt javac einen Compiler-Fehler: public class Einsatzwagen extends PKW { // Attribute: String Dienststelle = ""; // Konstruktor: Einsatzwagen(float Geschwindigkeit, float Gewicht, String Kennzeichen String Dienststelle) { ... Einführung in das Programmieren PKW() { // Hier passiert nichts. } 205/249 Einführung in das Programmieren Objektorientierung 12 13 14 15 16 17 Objektorientierung 19 20 21 22 23 } ... 24 25 Das Schlüsselwort extends ”erweitert” die Klasse PKW durch die Klasse Einsatzwagen. Dadurch sind die Zuweisungen in den Zeilen 11 – 13 zulässig, denn diese Attribute wurden von der Klasse PKW ”geerbt”. Einführung in das Programmieren ... // Methoden: void ausgeben() { super.ausgeben(); System.out.println("Dienststelle " + Dienststelle); } 18 ... this.Geschwindigkeit = Geschwindigkeit; this.Gewicht = Gewicht; this.Kennzeichen = Kennzeichen; this.Dienststelle = Dienststelle; 11 207/249 } Das Schlüsselwort super ruft die Methode ausgeben der Vaterklasse auf, da ihr Funktionskörper soweit übernommen werden kann. Lediglich die Ausgabe der Dienststelle wird von der Klasse Einsatzwagen übernommen. 206/249 Einführung in das Programmieren 208/249 Applets Objektorientierung Applets sind kleine Anwendungen, die auf einer Internet-Seite in einem eigenen Sicherheitskontext (sog. sandbox) ausgeführt werden. Durch diesen Sicherheitskontext wird gewährleistet, dass Applets keine persönlichen Daten auslesen oder private Daten zerstören können. Abschließend ist noch festzuhalten, dass alle Klassen eine gemeinsame Oberklasse, die Klasse Object (vgl. Java - API Dokumentation) besitzen. Darüber hinaus ist Mehrfachvererbung in Java im Gegensatz zu anderen objektorientierten Programmiersprachen unzulässig. Mit Applets werden einerseits multimediale Anwendungen (beispielsweise Laufbänder oder interaktive Menüs) realisiert, oder andererseits Anwendungen zur sicheren (verschlüsselten) Kommunikation, wie beispielsweise Online-Banking-Applets, bereitgestellt. Jedoch gibt es in Java die Möglichkeit, Schnittstellen (technisch durch das sog. interface realisiert) zu verwenden, um einer Klasse mehrere Väterklassen zu geben. Auf die Verwendung von Schnittstellen wird im nächsten Kapitel eingegangen. Einführung in das Programmieren Da ein Applet in einer Internet-Seite eingebettet ist, benötigt jedes Applet eine sog. HTML-Seite, um ausgeführt zu werden. 209/249 Einführung in das Programmieren 211/249 Applets Die allgemeine Struktur eines Applets sieht wie folgt aus: 1 import java.applet.*; 2 Applets 3 4 5 6 7 8 Einführung in das Programmieren 210/249 public class Beispiel extends Applet { public void init() { } } Einführung in das Programmieren 212/249 Applets Applets Die allgemeine Struktur eines Applets: 1 Die allgemeine Struktur eines Applets: 1 2 3 import java.applet.*; 4 2 3 5 ... 6 Java liefert eine Menge nützlicher Funktionen zur Erstellung von Applets in seiner Klassenbibliothek mit. Für Applets werden die benötigten Klassen wie o.a. eingebunden. Einführung in das Programmieren 1 Die ”main” - Funktion eines Applets ist die init - Funktion. Sie wird aufgerufen, wenn der Browser die Internetseite geladen hat und sie anzeigt. Neben der init - Funktion gibt es noch die destroy Funktion, die aufgerufen wird, wenn die Internet-Seite mit dem Applet geschlossen wird. 213/249 4 5 Einführung in das Programmieren Applets Applets Die allgemeine Struktur eines Applets: Applets sind in vielen Fällen graphisch orientiert, das bedeutet, sie stellen geometrische Objekte, Texte oder Steuerelemente, wie Buttons oder Textfelder, dar. import java.applet.*; public class Beispiel extends Applet { ... In der Methode paint können sämtliche Zeichenoperationen durchgeführt werden, angefangen von Linien, über Kreise bis hin zur Textausgabe. Jedes Applet ist eine Unterklasse des Klasse Applet. Die Klasse Applet stellt dabei wichtige Funktionen bereit, die für jedes Applet unverzichtbar sind, beispielsweise Start- und Stop-Funktionen. Einführung in das Programmieren 215/249 Graphische Objekte werden in Java auf einer virtuellen Leinwand gezeichnet. Diese virtuelle Leinwand existiert bereits zur Laufzeit des Applets. Um diese Leinwand zu verändern, stellt die Klasse Applet die Methode paint bereit. 2 3 import java.applet.*; public class Beispiel extends Applet { public void init() {} } Im folgenden wird ein Applet entwickelt, das auf einer gelben Leinwand den Text ”Hallo Internet” ausgibt. 214/249 Einführung in das Programmieren 216/249 Applets 1 2 Applets import java.applet.*; import java.awt.*; 4 5 3 4 5 6 7 8 9 10 11 12 6 public class Beispiel extends Applet { public void init() { setBackground(Color.yellow); } public void paint(Graphics gra) { gra.drawString("Hallo Internet.", 10, 20); } } Einführung in das Programmieren 7 8 9 10 11 ... public class Beispiel extends Applet { public void init() { setBackground(Color.yellow); } ... In der Methode init wird die Leinwand auf die Hintergrundfarbe gelb gesetzt. Die Farbe gelb ist eine konstante Klassenvariable der Klasse Color aus dem Paket java.awt. 217/249 Einführung in das Programmieren Applets Applets ... public void paint(Graphics gra) { gra.drawString("Hallo Internet.", 10, 20); } 12 1 2 3 13 import java.applet.*; import java.awt.*; ... 14 15 16 17 Neben dem Paket java.applet wird nun auch noch das Paket java.awt importiert. AWT ist das Akronym für abstract windowing toolkit. Im AWT werden Klassen bereitgestellt, die zur Gestaltung von graphischen Benutzeroberflächen (sog. GUIs) benötigt werden. Einführung in das Programmieren 219/249 } Die Methode paint ist in der Klasse Applet definiert. Sie wird jedes Mal aufgerufen, wenn die Leinwand neu gezeichnet werden muss. Eine Leinwand muss neu gezeichnet werden, wenn z.B. das Applet von einem anderen Fenster verdeckt wurde. 218/249 Einführung in das Programmieren 220/249 Applets Applets Mittels appletviewer Beispiel.htm sieht das Ergebnis wie folgt aus: Wenn die Leinwand neu gezeichnet werden muss, wird die Methode paint der Klasse Applet aufgerufen. Da diese Methode im Applet Beispiel überlagert wurde, wird die o.a. paint-Methode aufgerufen. Die Leinwand wird technisch durch die Klasse Graphics realisiert und besitzt im obigen Fall den Namen gra. Die Klasse Graphics stellt z.B. folgende Methoden zur Verfügung: drawLine, drawRectangle, drawOval und drawString. ! "# Die Methode drawString erwartet drei Parameter: Zunächst den Text, der dargestellt werden soll und anschließend die Koordinaten , an denen der Text gezeichnet werden soll. Einführung in das Programmieren 221/249 Applets Einführung in das Programmieren 223/249 Applets Die benötigte HTML-Datei sieht wie folgt aus: 1 2 3 4 5 <HTML> <APPLET code="Beispiel.class" width=300 height=300> </APPLET> </HTML> Als letztes Beispiel soll ein Applet entwickelt werden, dass bei einem Klick einer Maustaste einen blauen Kreis auf schwarzem Hintergrund zeichnet. Dazu wird das bisherige Applet der Art erweitert, dass es auf Ereignisse der Maus reagiert und die Koordinaten des Mauszeigers an die Zeichenfläche weiterleitet. Die Parameter width und height geben die Breite und Höhe des eingebetteten Bereichs an, in dem das Applet läuft. Einführung in das Programmieren 222/249 Einführung in das Programmieren 224/249 Applets 1 2 3 Applets import java.awt.*; import java.applet.*; import java.awt.event.*; 5 6 7 8 9 10 11 12 25 public class Kreis extends Applet implements MouseListener { int x = -1, y = -1; public void init() { setBackground(Color.black); ... Einführung in das Programmieren 26 27 28 29 30 31 225/249 Einführung in das Programmieren Applets 14 ... public {} public {} public {} public {} 32 33 } 34 16 17 18 19 20 21 22 23 35 public void paint(Graphics g) { g.setColor(Color.blue); if ( (x >= 0) && (y >= 0) ) g.fillOval(x - 5, y - 5, 10, 10); } ... Einführung in das Programmieren 227/249 Applets ... addMouseListener(this); 13 15 ... public void mouseClicked(MouseEvent evt) { x = evt.getX(); y = evt.getY(); repaint(); } ... 24 4 36 37 38 39 40 41 226/249 void mouseEntered(MouseEvent evt) void mouseExited(MouseEvent evt) void mouseReleased(MouseEvent evt) void mousePressed(MouseEvent evt) } Einführung in das Programmieren 228/249 1 2 3 Applets Applets Aufbau des Applets Kreis: Wenn nun eine Methode eine Referenz auf ein Objekt von Typ MouseListener erwartet, kann die Klasse Kreis angegeben werden, da sie die zugehörige Schnittstelle implementiert. import java.applet.*; import java.awt.*; import java.awt.event.*; Eine Schnittstelle zu implementieren bedeutet, alle Methodenrümpfe aus dem interface in der eigenen Klasse zu verwenden. 4 5 6 7 public class Kreis extends Applet implements MouseListener { ... Damit müssen folgende Funktionen aus der Schnittstelle MouseListener im Applet Kreis übernommen werden: mouseClicked, mouseEntered, mouseExited, mousePressed und mouseReleased. Zunächst wird zum AWT - Paket das Paket java.awt.event importiert. In diesem Paket sind verschiedene Klassen zur Behandlung unterschiedlicher Ereignisse, wie z.B. Tastatur- und Maus-Ereignisse, implementiert. Einführung in das Programmieren Das obige Applet benötigt nur die Methode mouseClicked. Somit können die Methodenrümpfe der anderen Methoden weiterhin leer gelassen werden. 229/249 Einführung in das Programmieren Applets Applets Unter anderem befindet sich in diesem Paket die Schnittstelle MouseListener. In dieser Schnittstelle sind alle Methoden gesammelt, die sich mit Ereignissen der Maus befassen. mouseClicked reagiert auf das Ereignis, wenn ein beliebiger Mausknopf gedrückt und wieder losgelassen wurde. Eine Schnittstelle ist technisch betrachtet eine Klasse ohne Kontruktor und mit leeren Methodenrümpfen (sog. abstrakte Klasse). Um eine Schnittstelle zu kennzeichnen, wird sie durch das Schlüsselwort interface eingeleitet. Schnittstellen werden über das Schlüsselwort implements in der eigenen Klasse eingebaut. mouseEntered wird ausgelöst, wenn der Mauszeiger in eine Steuerelement hingeschoben wird. mouseExited wird ausgelöst, wenn der Mauszeiger das Steuerelement wieder verlässt. mousePressed reagiert auf das Ereignis, wenn ein beliebiger Mausknopf gedrückt wird. Schnittstellen dienen dazu, das Verbot der Mehrfachvererbung zu umgehen. Im obigen Beispiel ist die Klasse Kreis beispielsweise eine Unterklasse von Applet, besitzt also alle Methoden und Attribute dieser Klasse. Darüber hinaus ist sie aber auch eine Klasse vom Typ MouseListener. Einführung in das Programmieren 231/249 mouseReleased wird ausgelöst, wenn ein beliebiger Mausknopf losgelassen wird. 230/249 Einführung in das Programmieren 232/249 Applets 9 10 11 12 13 14 17 18 19 20 21 22 ... public void paint(Graphics g) { g.setColor(Color.blue); if ( (x >= 0) && (y >= 0) ) g.fillOval(x - 5, y - 5, 10, 10); } ... Die Methode paint zeichnet einen blauen Kreis an den . Die Korrektur der Koordinaten in nichtnegativen Koordinaten Zeile 21 liegt darin begründet, dass Java als Startkoordinaten für den gefüllten Kreis nicht das Zentrum des Kreises verwendet, sondern die linke obere Ecke eines Quadrats, in das der Kreis eingebettet wird. ! 15 16 ... int x = -1, y = -1; public void init() { setBackground(Color.black); addMouseListener(this); } ... In den beiden Attributen x und y werden nach einem Mausklick die aktuellen Koordinaten des Mauszeigers gespeichert, um später an diesen Koordinaten den Kreis zu zeichnen. In Zeile 12 wird die Hintergrundfarbe eingestellt. Einführung in das Programmieren "# 8 Applets 233/249 Einführung in das Programmieren Applets 235/249 Applets 23 24 25 In der folgenden Zeile wird das Applet Kreis als ”Ereignis-Wächter” für Mausereignisse registriert. Die Methode addMouseListener erwartet ein Objekt vom Typ MouseListener. 26 27 28 Da die Klasse Kreis die Schnittstelle MouseListener implementiert, kann einfach die Referenz auf sich selbst (this) übergeben werden, um über entsprechende Mausereignisse informiert zu werden. 29 ... public void mouseClicked(MouseEvent evt) { x = evt.getX(); y = evt.getY(); repaint(); } ... Die Methode mouseClicked wird nach jedem Drücken eines Mausknopfes aufgerufen. Die Klasse MouseEvent beschreibt das Ereignis. Mittels evt.getX() lässt sich die -Koordinate des Mauszeigers auslesen. Darüber hinaus ließe sich beispielsweise noch auslesen, welcher Mausknopf gedrückt wurde. Einführung in das Programmieren 234/249 Einführung in das Programmieren 236/249 Applets Applets Die benötigte HTML-Datei sieht wie folgt aus: Nachdem die Koordinaten in die Attribute der Klasse Kreis übertragen wurden, wird die Methode repaint() aufgerufen. 1 Diese Methode sorgt dafür, dass die aktuelle Leinwand für ungültig erklärt wird, damit sie neu gezeichnet wird. 2 3 4 Wenn die Leinwand neu gezeichnet wird, verwendet die paint Methode die neuen Koordinaten, die nach dem Mausklick ausgelesen wurden, und es wird an dieser Stelle ein neuer Kreis gezeichnet. Einführung in das Programmieren 5 Die Parameter width und height geben die Breite und Höhe des eingebetteten Bereichs an, in dem das Applet läuft. 237/249 Applets ... public public public public 30 31 32 33 34 35 <HTML> <APPLET code="Kreis.class" width=300 height=300> </APPLET> </HTML> Einführung in das Programmieren 239/249 Applets Mittels appletviewer Kreis.htm sieht das Ergebnis wie folgt aus: void void void void mouseEntered(MouseEvent evt) {} mouseExited(MouseEvent evt) {} mouseReleased(MouseEvent evt) {} mousePressed(MouseEvent evt) {} } Die o.a. Methoden stammen aus der Schnittstelle MouseListener und müssen in der Klasse Kreis auftauchen, da sonst von javac ein Compiler-Fehler erzeugt wird. Von den obigen vier Methoden wird keine Funktionalität benötigt, darum ist der Methodenrumpf leer. Einführung in das Programmieren 238/249 Einführung in das Programmieren 240/249 Dokumentation Der Kommentar über mehrere Zeilen wird wie folgt verwendet: 1 2 3 Dokumentation 4 5 6 ... /* int zahl = 10; zahl = zahl * 4; System.out.println("Zahl=" + zahl); */ ... Somit werden alle Zeilen zwischen /* und */ während des Compiler-Vorgangs ignoriert. Einführung in das Programmieren 241/249 Einführung in das Programmieren Dokumentation 243/249 Dokumentation Der javadoc - Kommentar wird verwendet, um automatisch Programmdokumentation des Quelltextes erzeugen zu lassen: Bisher wurde nur ein einfacher Kommentarstil verwendet: 1 2 3 1 ... // int zahl = 10; ... 2 3 4 5 Java kennt allerdings noch zwei weitere Typen: Einen Kommentar, der über mehrere Zeilen verläuft und den javadoc - Kommentar. 6 7 8 9 Einführung in das Programmieren 242/249 ... /** Folgende Funktion dient der Berechnung der Fakultaet. @param n Eingabewert. @return Fakultaet von n. */ static int fakultaet(int n) { ... Einführung in das Programmieren 244/249 Dokumentation Dokumentation Nun kann über das Programm javadoc automatisch Dokumentation erzeugt werden: $ javadoc -private Fakultaet.java Loading source file Fakultaet.java... Constructing Javadoc information... Standard Doclet version 1.4.2 Generating constant-values.html... Building tree for all the packages and classes... Building index for all the packages and classes... Generating overview-tree.html... Generating index-all.html... ... Einführung in das Programmieren Die Firma Sun, Hersteller der Programmiersprache Java, hat unter http://java.sun.com/j2se/1.4.2/docs/api/ die Dokumentation zur Klassenbibliothek veröffentlicht. Dort werden alle Pakete, Klassen und Schnittstellen beschrieben. 245/249 Einführung in das Programmieren 247/249 Ende Einführung in das Programmieren 246/249 Einführung in das Programmieren 248/249 Bytecode, F. 10 plattformunabhängiger Zwischencode. Literatur [CU03] Christian Ullenboom. Java ist auch eine Insel (2. Aufl.). Galileo Computing, 2003. C [DWS02] Dr. Werner Struckmann. Programmieren I/II - Skript. 2001/2002. case sensitive, F. 17 Relevanz von Groß- und Kleinschreibung. [Krü03] Guido Krüger. Handbuch der Java-Programmierung. AddisonWesley, 2003. class, F. 22 Schlüsselwort und Auszeichnungsmerkmal der Objektorientierung von Java. [NM97] Petra Nootz and Franz Morick. C/C++ Referenz. Franzis, 1997. CLASSPATH, F. 43 Liste von Verzeichnissen, die nach vorkompilierten JavaKlassen durchsucht werden sollen. [SM03] Sun Microsystems. Java 2 Platform, Standard Edition, v 1.4.2 API Specification. http://java.sun.com/j2se/1.4.2/docs/api/, 2003. Compiler, F. 64 Programm zur Übersetzung von Quellcode in Bytecode, hier: javac. current working directory, F. 44 aktuelles Arbeitsverzeichnis. D Einführung in das Programmieren 248-1/249 Einführung in das Programmieren 248-3/249 Glossar Datentyp, F. 33 dient der Speicherung primitiver Daten, wie z.B. Zahlen oder Zeichen. A Definite Assignment, F. 59 automatische Vorbelegung einer neuen Variable mit einem gültigen Wert. Abbruchbedingung, F. 79 Bedingung, die zum Verlassen des Schleifenkonstrukts führt. abstract windowing toolkit, F. 218 Klassen zur Erstellung von graphischen Benutzeroberflächen (sog. GUIs). Applets, F. 8 kleine Anwendungen, die auf Internetseiten eingebettet sind. B Bedingungen, F. 108 dienen zur alternativen Aufspaltung des Programmablaufs. Block, F. 22 Anweisungen, die von geschweiften Klammern umgeben sind. Einführung in das Programmieren 248-2/249 Distribution, F. 13 Programmbündel aus Kernel und Anwendungsprogrammen. E EIP classes, F. 40 vorkompilierte Java-Klassen mit Funktionalit äten, die während dieses Praktikums benötigt werden. Endlichen Automaten, F. 157 dienen der eindeutigen und vollst ändigen Beschreibung einer endlichen Anzahl von Zustandsveränderungen. Endlosschleife, F. 81 Schleife mit (ungewollt) nicht eintretender Abbruchbedingung. Einführung in das Programmieren 248-4/249 F K Felder, F. 33 nummerierte Reihung eines gleichartigen Daten- oder Referenztyps. KDE, F. 15 komplettes Desktopsystem für Unix-artige Betriebssysteme. Funktionskörper, F. 91 Anweisungsblock einer Funktion. Klassenmethode, F. 185 Methoden einer Klasse, die nicht an die Lebensdauer eines bestimmten Objekts gebunden sind. G garbage collector, F. 171 Funktionalität von Java, unerreichbare Speicherstellen automatisch freizugeben. globale Variablen, F. 98 Variablen, auf die von mehreren Funktionen zugegriffen werden kann. H Home-Directory, F. 19 Verzeichnis, in dem sich der Anwender direkt nach dem Anmelden befindet. Einführung in das Programmieren Kernel, F. 13 Programm zur Verwaltung und Verteilung von Ressourcen. 248-5/249 HTML-Seite, F. 211 Beschreibungssprache für Internet-Seiten des World Wide Web. Klassenvariablen, F. 184 Attribute einer Klasse, die nicht an die Lebensdauer eines bestimmten Objekts gebunden sind. Kommentar, F. 242 dient zur Erhöhung der Lesbarkeit des Programmtextes oder zur zeitweisen Deaktivierung von Anweisungen. Konstanten, F. 183 Variablen, die zur Laufzeit nicht mehr verändert werden können. Konstruktor, F. 177 Spezielle Funktion einer Klasse, die zur Erzeugung eines Objekts dient. Einführung in das Programmieren 248-7/249 L Lebensdauer, F. 87 Gültigkeit von Variablen oder Funktionen. Logische Operatoren, F. 128 dienen zum Vergleich von booleschen Werten. I import, F. 41 Einbindung eines fremden Pakets im eigenen Quelltext. Integer, F. 94 Primitiver Datentyp zur Aufnahme von ganzzahligen Werten. M Interpreter, F. 10 Programm zur Ausführung des plattformunabhängigen Zwischencodes, hier: java. main, F. 26 Einstiegspunkt in ein Programm für den Java-Interpreter. Methodenrumpf, F. 238 Anweisungsblock einer Methode. Iteration, F. 77 Schleifendurchlauf. N J new, F. 50 Schlüsselwort der Objektorientierung zur Erzeugung eines neuen Elements. Java, F. 7 plattformneutrale Programmiersprache der Firma Sun. Einführung in das Programmieren 248-6/249 Einführung in das Programmieren 248-8/249 Relationale Operatoren, F. 125 dienen zum Vergleich von Ausdrücken zur Erzeugung eines booleschen Rückgabewerts. O Objekt, F. 177 Konkrete und einmalige Ausprägung einer Klasse. Objektorientierung, F. 23 Programmierparadigma zur alternativen Betrachtung eines Ausgangsproblems. S Schleifen, F. 56 Konstrukte zur gesteuerten Wiederholung von Anweisungen. P Parameterliste, F. 87 Liste von Argumenten, die einer Funktion oder einem Konstruktor übergeben werden müssen. Postinkrement-Anweisung, F. 73 zunächst wird der Wert der Variablen gelesen, bevor er erhöht wird. Präinkrement-Anweisung, F. 73 zunächst wird der Wert der Variablen erhöht, bevor er gelesen wird. Schleifenkörper, F. 76 Anweisungsblock, der mehrfach wiederholt werden kann. Schleifenkopf, F. 76 Kontroll- und Steuerkonstrukt einer Schleife. Schnittstelle, F. 230 Abstrakte Klasse zur Ermöglichung von Mehrfachvererbung. Scoping, F. 101 Gültigkeit einer deklarierten Variable. Primitive Datentypen, F. 58 dienen der Speicherungen von Zahlen und Ziffern, z.B. int oder char. Shell, F. 16 mächtige Eingabeaufforderung zur direkten Eingabe von Befehlen. Einführung in das Programmieren Einführung in das Programmieren 248-9/249 248-11/249 Prozeduren, F. 30 Funktionen, die keinen Rückgabewert liefern und damit das Schlüsselwort void tragen. Short-Circuit-Evaluation, F. 131 teilweise Auswertung eines Wahrheitsausdrucks. public, F. 22 Schlüsselwort und Auszeichnungsmerkmal der Objektorientierung von Java. Sichtbarkeit, F. 87 siehe Sichtbarkeitsoperatoren. Sichtbarkeitsoperatoren, F. 23 dienen der Einschränkung des Zugriffs auf Klassen, Variablen oder Funktionen. Q Signatur, F. 91 Art und Reihenfolge von Parametern einer Funktion. Quelltext, F. 21 Programmcode in lesbarer Form für Menschen. Standardkonstruktor, F. 188 Konstruktor ohne Argumentenliste. R static, F. 29 Schlüsselwort und Auszeichnungsmerkmal der Objektorientierung von Java. Referenztyp, F. 31 enthält den Verweis auf eine Speicherstelle, an der sich die eigentlichen Daten befinden. Rekursionen, F. 113 wiederholtes Aufrufen der eigenen Funktionen. Beispiel: Fakultätenfunktion. Einführung in das Programmieren 248-10/249 STDOUT, F. 37 Ausgabekanal für System.out. String, F. 30 Datentyp, der Zeichenketten aufnehmen kann. T Einführung in das Programmieren 248-12/249 TurtleScreen, F. 50 Java-Klasse zur Darstellung eines graphischen Fensters, auf dem sich eine Schildkröte bewegen kann. U Umgebungsvariable, F. 45 Parameter in der Shell. UML-Diagramm, F. 201 ist ein Element der Unified Modelling Language zur Modellierung von objektorientierten Zusammenhängen. Unicode-Buchstaben, F. 60 Zeichentabelle für bis zu 4.294.967.296 Zeichen. V Vererbung, F. 200 Ableiten einer neuen Klasse unter Zuhilfenahme der Attribute und Methode einer vorhandenen Klasse. Einführung in das Programmieren 248-13/249 void, F. 35 Leerer Datentyp, der angegeben wird, wenn kein Rückgabewert benötigt wird. W Wahrheitstabellen, F. 129 tabellarische Auswertung eines Wahrheitsausdrucks. Y y-Nummer, F. 14 Anmeldungskennziffer, im Rechenzentrum erhältlich. Z Zählvariable, F. 78 dient zur Steuerung des Schleifenkörpers durch den Schleifenkopf. Einführung in das Programmieren 248-14/249