Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Java als objektorientierte Programmiersprache Allgemeines zu Programmiersprachen Was ist Java? Allgemeines zu Java Installation von Java Algorithmen Darstellungsmethoden Schritte zur Programmentwicklung Primitive Datentypen Kontrollfluss und Schleifen Strings Arrays Klassen und Objekte Vererbung von Klassen Exceptions Interface Applets Events Graphische Benutzeroberfläche Streams Threads Ergänzungen 1 Einführung Was ist eine Programmiersprache? Sprache, die entwickelt wurde, um einen Computer zu instruieren bestimmte Dinge zu tun. Was ist ein Programm? Ein Algorithmus, der mittels einer Computerprogrammiersprache geschrieben wird. Was ist ein Algorithmus? Eine präzise Methode die ein Computer zur Lösung von Aufgaben/Problemen benutzt. Algorithmus ist aus endlicher Menge von Schritten aufgebaut. Ein Schritt besteht aus einer oder mehreren Operationen. 2 Einführung 1. Übungsaufgabe: Schreibe einen Algorithmus, der die Zahlen von 1 bis 2000 (allgemein n) aufsummiert und das Ergebnis ausgibt! Vorgehensweise: initialisiere summe mit 0 initialisiere zahl mit 0 solange zahl <= 2000 wiederhole: addiere zahl zu summe erhöhe zahl um eins gib summe aus Pseudocode: summe = 0 zahl = 1 while (zahl <= 2000) { summe = summe + zahl zahl = zahl + 1 } print “Die Summe ist“, summe 3 Einführung Welche Sprachen gibt es? Maschinensprache: interne Sprache des Rechners/Prozessors Befehle sind binär codiert (Darstellung jedoch häufig hexadezimal) Bsp: op-code: A1 10E4 04 2a a3 10e4 (hole Inhalt der Speicherzelle 10e4h in a1- register) (addiere zum Inhalt des a1- Register eine 46) Speicher Inhalt des a1- Registers in Speicherzelle 10e4) Assembler: nur für Prozessor eines Typs gültig: Befehlscodes werden durch Mnemotechnische Abkürzungen dargestellt (MOV, ADD, MULT, INC,...) Speicheradressen können symbolisch benannt werden Problemorientierte, prozedurale (höhere Programmiersprachen) Vertreter: Fortran, Cobol, Algol, C, C++, PASCAL, java, ... höhere Rechnerunabhängigkeit (Portabilität) Notation in Form von Anweisungen. 4GL, oder deklarative Sprachen: z.b. Abfragesprachen für DB 4 Was ist Java? Die Programmiersprache Java ist eine Plattform (bestehend aus Java- Compiler und Java Interpreter) eine Systemprogrammiersprache (wie C/ C++, Pascal, Fortran, ...) zum Schreiben von Programmen von der Syntax ähnlich der Sprache C einsetztbar zum Schreiben von Applets eingesetzt Vergleich zwischen Java und anderen Programmiersprachen (aus Oust[98]): 5 Was ist Java? • Das Bild zeigt die Einordnung von Programmiersprachen in Abhängigkeit von Maschineninstruktionen/ Anweisung und dem Grad der Typisierung. • Während interpretierte Skriptsprachen wie perl, tcl zumeist eine lose Typisierung besitzen (d.h. es gibt z.B. keinen expliziten Datentyp für eine floatZahl oder eine Zeichenkette) sind Systemprogrammiersprachen streng typisiert, was eine effektivere Fehlererkennung zum Compilierzeitpunkt erlaubt. • Skriptsprachen führen pro Anweisung eine höhere Anzahl von Maschineninstruktionen aus, was zu kürzeren Programmen führt. • Systemprogrammiersprachen und Skriptsprachen können sich auf ideale Weise ergänzen, indem komplexe Komponenten in einer Systemprogrammiersprache entwickelt werden und diese Komponenten dann anschließend mittels Skriptsprachen flexibel zu fertigen Anwendungen kombiniert werden können. 6 Was ist Java? Eigenschaften von Java: einfach objektorientiert architekturneutral (portabel) verteilt sicher multithreaded dynamisch performant 7 Was ist Java? 1. einfach: Kleine Anzahl an Sprachelementen Fehlen einer Reihe von komplizierten / fehleranfälligen Sprachkonstrukten (keine Pointerarithmetik/Pointer, keine Speicherallokation sondern Garbage Collection Umfangreiche bestehende Klassenbibliotheken (zuerst abschreckend, dann ..., einfach mal rumbrowsen) 8 Was ist Java? 2. objektorientiert: Natürlichere Entwurfsphilosophie als bei prozeduralen Sprachen Einheitliche Behandlung von Daten und Programmcode in Form von Klassen Aufbau von Klassenhierarchien (Vererbung) Objekte bestehen aus Daten (beschreiben Zustand des Objektes) und Methoden (beschreiben Verhalten des Objektes) einfacher zu lesen, effizientere Wiederverwendbarkeit, schnellere Entwicklungszeiten, robuster/ weniger fehleranfällig 9 Was ist Java? 3. architekturneutral: Java Programme sind plattformunabhängig, d.h. sie können auf jeder Rechnerplattform ablaufen für die eine Java virtuelle Maschine existiert. Java Compiler erzeugt plattformunabhängigen Bytecode, der dann zur Laufzeit von der Java virtual machine (VM) interpretiert wird (siehe Folie). Java virtuelle Maschine kapselt alle betriebs/hardwarespezifischen Eigenschaften der Rechnerplattform und stellt dem Java Programm eine neutrale Laufzeitumgebung zur Verfügung. Aspekt der plattformunabhängigkeit in Bezug auf Applets wichtig 10 Was ist Java? 4. architekturneutral: Java Standardbibliothek unterstützt in hohem Maße verteiltes Programmieren (eine Reihe von existierenden Klassen die Kommunikation verteilter Prozesse unterstützen -- java.netklassen, z.b. URL Klasse); , RMI (Remote Method Invovcation) aber auch Kommunikation über Sockets bzw. UDT/ datagramme; applets) 11 Was ist Java? 5. sicher: Fehlen von fehleranfälligen Konstrukten wie Pointer, Speicheralllokation streng typisierte Sprache (d.h. jede Variable hat einen fest vorgegebenen Typ (boolean, int, long, float, char, string) Ausnahmebehandlung -> klarer strukturierter Code Interpreter überprüft Bytecode zur Laufzeit Applet Sandboxprinzip (eingeschränkte Funktionalität) 12 Was ist Java? 6. multithreaded: Gleichzeitig mehrere Ausführungsstränge in einem Programm (z.B. ausführen umfangreicher Berechnungen und gleichzeitig Interaktion mit Benutzer) 13 Was ist Java? 7. dynamisch: Klassen können zur Laufzeit dynamisch nachgeladen werden und Objekte daraus instanziiert werden. 14 Was ist Java? 8. performant: prinzipiell sind interpretierte Programme langsamer als z.B. compilierter (plattformabhängiger) C-Code (Daumenregel: ca. faktor 10) Geschwindigkeit ae4r für Grossteil der Anwendungsfelder ausreichend, z.B. Datentransport, Benutzerinteraktion. JIT Compiler (Just In Time) übersetzt Java Bytecode zur Laufzeit in plattformabhängigen Maschinencode Weitere native-compilers in Entwicklung Zeitkritische Anwendungen können weiterhin in C/Fortran geschrieben werden und dann in das Java Programm eingebunden werden. 15 Was ist Java? 9. architekturneutralität 16 Was ist Java? Online Klassenbrowser 17 Was ist Java? Einordnung Applets sind Java Programme die in einer HTML-Seite integriert sind Java fähige WWW-Browser (Netscape, MS-IE) haben eine VM integriert SDK von SUN ist eine Entwicklungsumgebung zur Entwicklung von Java Programmen oder Applets. weitere Entwicklungsumgebungen: Java Workshop (SUN), Cafe (Symantec), Visual J++ (Microsoft), Roaster (Natural Intelligence), Kawa (TekTools), JOE Applets laufen innerhalb eines Browsers oder Appletviewer (SUN) ab Java ist nicht Javascript 18 Was ist Java? Die Java Umgebung JDK von SUN Compiler: javac Debugger: jdb Laufzeitumgebung: java, jre Dokumentationstool: javadoc Appletviewewér: appletviewer Packer: jar Integrated Development Environments (IDE) bestehend aus: Projektmanager, Edit-CompileDebug Prozess, kontextsensitive Hilfe, GUI-Builder, Versionsverwaltung, Templates, zusätzliche Klassenbibliotheken • Beispiele: Borland JBuilder, Sun Forte, Micro-soft Visual J++, ... 19 Allgemeines zu Java Einsatz des JDK von SUN • Mit beliebigem Editor (z.B. notepad) Programmcode erstellen: public class Summe { public static void main (String args[ ]) { int summe = 0; int limit = 1000; int zahl = 1; while (zahl <=limit) { summe = summe + zahl; zahl = zahl + 1; } System.out.println("Die Summe von 1 bis " + limit + " betraegt:" + summe); } } • Datei unter dem Namen Summe.java abspeichern • Datei Summe.java compilieren (Datei Summe.class wird erzeugt): javac Summe.java • Programm ausführen: java Summe • Ausgabe: Die Summe von 1 bis 1000 betraegt: 500500 20 Installation von Java Download des JDK: Download von Java (Win95/NT) 21 Installation von Java Installation von Java (Win95/NT) 22 Installation von Java Installation von Java (Win95/NT) Modifiziern des Zugriffspfad in der Autoexec.bat Datei (nur Win95/98): 23 Algorithmen Ein Algorithmus ist ein Verfahren zur systematischen, schrittweisen Lösung eines Problems. Er besteht aus einzelnen Anweisungen, die in einer bestimmten Reihenfolge, evtl. mehrmals ausgeführt werden müssen. Beispiele: • ärztliche Verordnung: nimm 3x täglich 15 Tropfen einer Medizin ein • Spielregeln, z.B. Mensch-ärgere-dich-nicht • Verfahren zur Addition und Multiplikation von 2 Dezimalzahlen • Näherungsverfahren zur Bestimmung der Quadratwurzel konkretes Beispiel: Algorithmen zum Test auf Primzahl Eine Primzahl ist eine ganze Zahl >1, welche nur durch sich selbst und durch den Wert 1 teilbar ist. Die Folge der Primzahlen lautet 2, 3, 5, 7, 11, 13, ... ZAHL sei 7und ZAHL sei 9 7 : 2 teilbar? => nein 9 : 2 teilbar? => nein 7 : 3 teilbar? => nein 9 : 3 teilbar? => ja 7 : 4 teilbar? => nein 9 : 4 teilbar? => nein 7 : 5 teilbar? => nein 9 : 5 teilbar? => nein 7 : 6 teilbar? => nein usw. ... => 7 ist eine Primzahl => 9 ist keine Primzahl 24 Algorithmen Algorithmus: Gebe eine ZAHL ein Setze DIVTEST = 2 SOLANGE ((DIVTEST kleiner ZAHL) und (ZAHL nicht durch DIVTEST teilbar)) Erhoehe DIVTEST um 1 WENN (DIVTEST gleich ZAHL) DANN Ausgabe ZAHL ist Primzahl SONST Ausgabe ZAHL ist keine Primzahl 25 Grundstrukturen von Algorithmen Allgemeine Anweisungen (oder Aktionen), werden ohne Einschränkung ausgeführt. Bei bedingte Anweisungen (oder Auswahl) werden Programmteile nur bei bestimmten Daten ausgeführt , man spricht von bedingten Anweisungen. Man unterscheidet: Einfache bedingte Anweisung, bestehend aus Bedingung und Anweisung, die ausgeführt wird, wenn die Bedingung erfüllt ist. Die Bedingung ist ein Ausdruck, der als Ergebnis einen Wahrheitswert der Form wahr oder falsch liefert. Die Anweisung ist eine beliebige Anweisung (z.B. wieder eine bedingte Anweisung) Vollständige bedingte Anweisung besteht aus beiden Elementen einer bedingten Anweisung und zusätzlich einer Anweisung, die ausgeführt wird, falls die Bedingung nicht erfüllt ist. Das hat zur Folge, daß immer eine der beiden Anweisungen ausgeführt wird Fallunterscheidung, falls es mehr als zwei Fälle gibt. Dann definiert man statt einer Bedingung, die entweder wahr oder falsch sein kann, einen so genannten Verteiler, der mehrere Werte annehmen kann. Analog gibt es statt 2 möglichen Alternativen (Aktion 1 und 2) mehrere mögliche Alternativen (Aktion 1 ... n). Schleifen (oder Wiederholungen), bei denen die Daten bestimmen, wie oft ein bestimmtes Programmstück durchlaufen werden soll. Schleifen bestehen i. d. R. aus 3 Teilen: • • • Vorbehandlung, d.h. einer Initialisierung der Anfangswerte Anweisungen, die innerhalb der Schleife wiederholt ausgeführt werden. Diese müssen u.a. auch die Schleifenvariable verändern , die dann getestet werden kann. Test auf Bedingung für den Abbruch oder Fortsetzen der Schleifen anhandder Schleifenvariable. 26 Grundstrukturen von Algorithmen Es gibt 3 Arten von Schleifen: • Zählschleifen, bei denen ein Programmabschnitt n-mal durchlaufen wird. Dabei muß die Anzahl der Schleifendurchläufe bekannt sein. (Es gibt Programmiersprachen, insbesondere Java, in deren Sprachumfang echte Zählschleifen nicht vorkommen.) • Bedingte Schleifen, bei denen ein Abschnitt eines Programms solange durchlaufen wird, bis ein Testkriterium greift. Zu Beginn ist die Anzahl der Durchläufe aber unbekannt (sonst i. d. R. Zählschleife). Bedingte Schleifen unterteilt man, je nachdem, wann der Test durchgeführt wird, in: – While-Schleifen, bei denen der Test vor jedem Schleifendurchlauf erfolgt. Die Ausführung der Anweisungen erfolgt, solange die Schleifenbedingung erfüllt ist. – Repeat-Schleife (do-while), bei denen der Test nach jedem Schleifen-durchlauf erfolgt. Das bedeutet, daß die Schleife mindestens einmal durchlaufen wird. Die Interpretation ist abhängig von der Programmiersprache: – In PASCAL z.B. erfolgt die Ausführung der Anweisung, bis das Abbruchkriterium erfüllt ist. Das Abbruchkriterium dieser Schleife ist demnach die Negation der Schleifenbedingung bei der äquivalenten While-Schleife. – In Java dagegen erfolgt die Ausführung der Anweisung, solange die Schleifenbedingung erfüllt ist. Die Formulierung der Schleifenbedingung ist demnach analog zur While-Schleife. 27 Darstellungsmethoden Mit Hilfe von Flußdiagrammen kann man den Ablauf eines Algorithmus recht übersichlich beschreiben. Dabei gibt es unterschiedliche Symbole für verschiedene Typen von Anweisungen, die genormt sind (DIN 66001): Allgemeine Anweisung (Aktion) Ein-/Ausgabeanweisung Anfangs-/Endmarkierung Bedingte Anweisung Bild Diese Grundsymbole werden über Pfeile miteinander verbunden, um die Ablaufreihenfolge darzustellen. Der Nachteil besteht darin, daß es nicht für alle Anweisungsformen (z.B. Schleifen) geeignete Symbole gibt. Man kann (wie in der Tabelle) auf Nichts-Standard-Symbole ausweichen oder diese Anweisungsformen recht kompliziert mit Hilfe der angebotenen Symbole realisieren. Nachteil der Flußdiagramme: sie ermöglichen eine übersichtliche Darstellung eines Ablaufens, sie erzwingen diese aber nicht. 28 Darstellungsmethoden Tabelle 29 Beispiel: GGT Beispiel: Bestimme GGT von 24 und 15: 24:15 = 1 Rest 9 15 : 9 = 1 9:6=1 6 :3 = 2 Rest 6 Rest 3 Rest 0 GGT = 3 Ein Algorithmus dafür in natürlichsprachlicher Form hat die folgende Gestalt: Lies a und b Falls b > a vertausche a und b Falls b > 0 Setze zahl a = a und zahl b = b wiederhole: rest = zahl a modulo zahl b zahl a = zahl b zahl b = rest solange rest ungleich 0 Drucke "zahl a ist der GGT von a und b" sonst Drucke " ungültige Eingabe" 30 Flußdiagramm Flussdiagramm 31 Struktogramm 32 Beispiel: Zins Es soll ein Algorithmus zur Berechnung von Zinseszinsen erstellt werden. Zur Erinnerung sei das Problem hier kurz skizziert: Bei jährlicher Verzinsung für ein gegebenes Ausgangskapital K 0 einem Zinssatz p erhält man Zinsen in Höhe von z = K 0 * p /100. Das Gesamtkapital K 1 nach einem Jahr beträgt daher: K 1 =K 0 * (1 + p / 100). Wenn man dieses neu erhaltene Kapital weiterverzinst, so erhält man durch Wiederholung die Zinseszinsformel für das Endkapital K (n) nach n jähriger Verzinsung: K (n) = K 0 * (1 + p /100) hoch n . Die Berechnung benötigt also folgende Eingabedaten: • • • Ausgangskapital K_0 Zinssatz p Verzinsungsdauer n in Jahren Der Algorithmus soll diese drei Werte einlesen, und zunächst auf Gültigkeit überprüfen, beispielsweise ist eine negative Verzinsungsdauer ungültig. Falls einer der drei Werte unzulässig ist, soll der Algorithmus mit einer qualifizierten Fehlermeldung abbrechen. Wenn alle drei Werte zulässig sind, soll der Algorithmus zunächst diese Werte ausgeben, und dann eine Tabelle folgender Form erstellen: (Beispiel p = 5%) 33 Natürlichsprachlicher Algorithmus Start Zinseszins Lies Startkapital WENN Startkapital<0 DANN Ausgabe "Negatives Startkapital" SONST Lies Zinssatz WENN Zinssatz<0 DANN Ausgabe "Zinssatz negativ" SONST Lies Dauer WENN Dauer<0 DANN Ausgabe "Dauer negativ" SONST Kapital = Startkapital Zins = 0 Jahr = 0 SOLANGE Jahr <=Dauer Ausgabe Jahr, Zins, Kapital Beginne neue Ausgabezeile Zins = Kapital * Zinssatz/100 Kapital = Kapital + Zins Jahr = Jahr + 1 Ende Zinseszins 34 Struktogramm 35 Flussdiagramm 36 Schritte zur Programmentwicklung 1. Formulierung des Problems 2. Entwurf eines Lösungsalgorithmus Formulierung auf abstrakter Ebene Beachten von Strukturregeln Korrektheit des Lösungsalgorithmus prüfen Effizienzuntersuchungen 3. Implementierung, d.h. Übertragung des Lösungsalgorithmus in eine Programmiersprache. Ergebnis: ein Programm als Quellcode 4. Übersetzen (engl.: to compile) des Programms in eine maschinennahe Sprache Das geschieht durch den Compiler (javac). Das Ergebnis ist Bytecode 5. Ausführen des Programms (java) 37 Beispiel 1. Formulierung des Problems Berechne den Quotienten zweier Zahlen a,b (d.h. a/b), falls b ¹ 0, sonst melde, daß b ein unzulässiger Wert ist. 2. Entwurf eines Lösungsalgorithmus Start Lies zwei Zahlen a und b ein WENN b ungleich 0 DANN quotient sei a / b schreibe quotient SONST schreibe "b ist ein unzulaessiger Wert" Ende ... Strukturregeln, Korrektheit, Effizienz 3. Implementierung (Speichern als Quotient.java) import Utils; class Quotient { public static void main (String args [ ]) { float a,b, quotient; a = Utils.inputFloat(„Gib a ein: „); b = Utils.inputFloat(„Gib b ein: „); if (b!=0) { quotient = a/b; System.out.println(„Quotient „+quotient); } else { System.out.println(b+“ ist unzulaessiger Wert“); } } } 38 Beispiel 4. Übersetzen: javac Quotient.java 5. Ausführen: misun3:65>java Quotient Gib a ein: 3 Gib b ein: 6 Quotient 0.5 misun3:66>java Quotient Gib a ein: 3 Gib b ein: 0 0.0 ist unzulaessiger Wert 39 Aufgaben Aufgabe 1 Erstelle einen Algorithmus zum Aufbau einer Temperaturtabelle von Fahrenheit (F) nach Celsius (C). Die Tabelle soll bei 0 F beginnen und bei 300 F enden. Die Abstände der Stützstellen sollen 20 F betragen. Der funktionale Zusammenhang von F und C ist durch folgende Formel gegeben: C = (5 / 9) * ( F - 32) Beispiel: Temperaturtabelle Fahrenheit I 0 I .. 300 Celsius -17.8 I 148.9 Aufgabe 2 Der Wildbestand eines Forstes umfasst 200 Stück. Die jährliche Vermehrung beträgt 10%; zum Abschuß sind im gleichen Zeitraum 15 Stück freigegeben. Wie entwickelt sich der Bestand in den nächsten Jahren? Erstelle eine Algorithmus, der den jährlichen Wildbestand ermittelt, bis dieser die Zahl 300 erreicht hat. Aufgabe 3 Entwickle einen Algorithmus, der das kleine Einmaleins in Tabellenform (10 mal 10 Tabelle) ausgibt. Aufgabe 4 Schreibe einen Algorithmus, der beliebig, viele Zahlen einliest und diese Zahlen aufsummiert. Als Abbruchkriterium verwende die Eingabe einer negativen Zahl. (Realisierung einmal mit while-Schleife und einmal mit dowhile Schleife.) 40 Primitive Datentypen 2 Arten von Datentypen: primitive Datentypen (heute) Objekte (später) Java ist streng typisiert, d.h. für jede Variable muß angegeben werden was für eine Art von Wert sie aufnimmt • Beispiele: double radius; float umfang; int anzahl = 2; char a = ‘c’; 41 Operatoren mathematische Operatoren: logische Operatoren Konstanten soll eine Variable nicht geändert werden dürfen, so wird es mit dem Attribut final versehen: final float PI = 3.141592f; 42 Ausgabe In der Klasse java.lang.System realisiert Drei Streams: Standardausgabe: System.out Standardfehlerausgabe: System.err Standardeingabe: System.in Ausgabe auf Konsole (stdout, stderr): System.out.println ("Ich bin eine Zeile"); System.out.print ("Ich bin"); System.out.println (" eine Zeile"); System.err.println ("Aaaargghh ich steeer...."); 43 Hello World Ein erster Programmierversuch: Datei HelloWorld.java in Editor (z.B. no-tepad) erstellen: class HelloWorld { public static void main (String args[ ]) { System.out.println("Hello World!"); } } DOS Fenster öffnen Programm übersetzen: d:\user\smiff> javac HelloWorld.java Wenn kein Fehler aufgetreten ist, wurde die Datei HelloWorld.class angelegt d:\user\smiff\> dir Hello* HelloWorld.class HelloWorld.java d:\user\smiff> Programm laufen lassen: d:\user\smiff> java HelloWorld Alternative: Verwendung von Joe 44 Eingabe • Einlesen von Konsole: (mit Ausnahmebehandlung): byte buffer[ ] = new byte[80]; int num_char; String input = ""; System.out.print("Bitte gib mal was ein: "); try { num_char = System.in.read(buffer, 0, 80); input = new String(buffer,0, num_char); } catch (IOException e) { System.err.println("IO Fehler"); } System.out.println(">>>>>>" + input); } Benutzung der Klasse Utils: Zur Vereinfachung kann die Klasse Utils in das Programm im-portiert werden, die das Einlesen erleichtert. Utils ist auf der Homepage verfügbar. 45 Beispielprogramm zur Eingabe import Utils; class InputDemo { // kleines Demo Programm zur Demonstration // der Eingabemethoden // Utils.inputInteger(...) // Utils.inputString(...) // Utils.inputFloat(...) public static void main(String argv[ ]) { String str = Utils.inputString(" gib Text ein:"); int z = Utils.inputInteger("und jetzt ne Zahl:"); float f = Utils.inputFloat("und ne Gleitkommazahl:"); System.out.println(" String: " + str ); System.out.println("Integer: " + z ); System.out.println("Float: " + f); } } 46 Kontrollfluß und Schleifen if – else if (boolscher Ausdruck) statement else statement Beispiel: if (a % 2 == 0) { System.out.println(“a ist gerade“); } else { System.out.println(“a ist ungerade“); } While Schleife while (boolscher Ausdruck) statement Beispiel: i = 1; a = 0; while (a < 10) { a = a + i; i = i + 1; } 47 Beispiel Ausgabe der Zahlen von 1 bis 100: class Ausgabe1bis100 { public static void main (String args []){ int i=1; while ( i<101) { System.out.println(i); i++; } } } 48 Schleifen do – Schleife do statement while (boolscher Ausdruck); Beispiel (Test zu Beginn/Ende der Schleife): do { System.out.println(a); a++; } while (a < 50); while (a < 50) { System.out.println(a); a++; } for – Schleife for (init; boolscher Ausdruck; Schritt) statement Beispiel: for (int i = 1; i < 100; i++) { System.out.println(“i = “ + i); } 49 Beispiel Ausgabe der Zahlen von 1 bis 100 mit do-while: class Ausgabe1bis100 { public static void main (String args []) { int i=1; do { System.out.println(i); i++; } while ( i<101); } } Ausgabe der Zahlen von 1 bis 100 mit for: class Ausgabe1_100 { public static void main (String args [ ]) { for (int i=1; i<101; i++) System.out.println(i); } } 50 Beispiel Aufsummieren der Zahlen von 1 bis 50 public class Summe { public static void main (String args[]) { int summe=0; for (int i= 1; i<=50; i++) summe = summe + i; System.out.println (“ summe = “+ summe); } } 51 Breakanweisung break: Beendigung der Schleife und fortfahren mit der nächsten Anweisung nach der Schleife while (true) { if (i++ > 100) break; System.out.println(“i=“ + i); } continue: Abbruch des aktuellen Schleifendurchlaufs und Sprung zum nächsten Schleifendurchlauf while (i <=100) { if (i++ % 2) continue; System.out.println(i); } 52 Switchanweisung Switch Statement switch (Selektor) { case wert1: statement; break; case wert2: statement; break; // ... default: statement; } Beispiel: public class Switch { public static void main (String args[ ]) { for (char c=65; c < 91; c++) { switch (c) { case ‘A’: case ‘E’: case ‘I’: case ‘O’: case ‘U’: System.out.println(c + „ ist ein Vokal“); break; case ‘X’: System.out.println(„Das „ + c +“ ist mein Lieb-lingsbuchstabe“); break; default: System.out.println(c + „ ist ein Konsonant“); } } } } 53 Strings Ein String ist ein Java Objekt Erzeugung: String s1 = "Hallo"; String s2 = new String("wie gehts"); String s3 = "Ein \"String\" mit Anführungszeichen"; Verkettung von Strings: String s4 = s1 + " " + s2 + "?"; Umwandlung einfacher Datentypen in Strings: float f = 1.234f; String s = Float.toString(f); Umwandlung von Strings in einfache Datentypen: String intStr = "353"; int i = Integer.parseInt(intStr); short s = Short.parseShort(intStr); Methoden der Klasse String: Vergleich: boolean equal = s1.equals(s2) equal = s1.equalsIgnoreCase(s2); Länge ermitteln: int len = s1.length() Liste aller Methoden : http://java.sun.com/products/jdk/1.2/docs/api/java/ lang/String.html 54 Beispiele Programm das alle durch 3, 5 oder 7 teilbaren Zahlen kleiner 200 ausgibt: class C357 { public static void main (String args []) { for (int i=1; i<201; i++) if (i%3 == 0 || i%5 == 0 || i%6 == 0) System.out.println(i+“ ist durch 3,5 oder 7 teilbar“); } } 55 Beispiele Programm, das die folgende Ausgabe erzeugt: * *** ***** ******* ********* *********** class Baum { public static void main (String args [ ]) { int zeilen=10; for (int i = zeilen; i >0; i--) { for(int j=0;j<i;j++) System.out.print(„ „); for(int j=0;j<2*(zeilen-i)-1;j++) System.out.print(„*“); System.out.println(); } } } 56 Aufgaben Erstellen Sie zu den in den Aufgaben 1 bis 4 aus der Vorlesung „Algorithmen“ erstellten Algorithmen die zugehörigen JavaProgramme. 57 Arrays Eindimensionale Arrays Erzeugen (2 Möglichkeiten): • Erzeugung durch new-Operator: float v[ ] = new float[4]; 58 Arrays • Arrays sind Objekte • Sie werden dynamisch erzeugt • Sie werden automatisch vom Garbage Collector entfernt • Aber kein Konstruktor, sondern new-Operator • Anzahl der Komponenten des Arrays muß bei der Definition angegeben werden • Die Länge des Arrays erhält man durch das length-Attribut desArrays (v.length ist in unserem Beispiel gleich 4) • Die Indizes der Komponenten müssen ganzzahlig sein • Die Komponenten selbst werden mit 0 beginnend numeriert • Der größte zulässige Index ist immer um 1 kleiner ist als die Anzahl der Komponenten (length-1) • Negative Indizes und Indizes größer oder gleich der Länge length sind nicht zugelassen (z.B. [v.length] führt zum Fehler) • Die Elemente eines auf diese Weise erzeugten Arrays werden mit dem für diesen Typ üblichen Standardwert initialisiert. (Bei unserem Array v beispielweise mit 0.0f.) • Direkter Zugriff auf jede Komponente (z.B. v[1] = 1.2) 59 Arrays • Erzeugung durch einen Initialisierer: int lt[ ] = {1,2,4,8,16,32,64,128}; • Diese Syntax erzeugt auf dynamische Weise einen Array und initialisiert seine Elemente mit den angebenen Werten Beispiel: (Ausgabe des Arrays lt) public class lt { public static void main(String[ ] args) { int lt[ ] = {1,2,4,8,16,32,64,128}; for(int i = 0; i < lt.length; i++) System.out.println(lt[i]); } } Beispiel: (Summe des Arrays lt) public class lt { public static void main(String[ ] args) { int lt[ ] = {1,2,4,8,16,32,64,128}; int summe =0; for(int i = 0; i < lt.length; i++) summe = summe + lt[i]; System.out.println("Summe: " +summe); } } 60 Arrays Beispiel: (Erzeugen eines Feldes mit Zufallszahlen als Inhalt) public class MyArray { public static void main(String[ ] args) { double nums[] = new double[10]; for (int i = 0; i < nums.length; i++) nums[i] = Math.random() * 100; for (int i = 0; i < nums.length; i++) System.out.println(nums[i]); } } Beispiel: (Suchen des größten Wertes im Array) public class ArrayGreat { public static void main(String[ ] args) { double [ ] nums = new double[10]; //Klammernb koennen auch hier stehen for (int i = 0; i < nums.length; i++) nums[i] = Math.random() * 100; int max=0; //Index des groessten Elementes for (int i = 1; i < nums.length; i++) if (nums[max]<nums[i]) max = i; System.out.println("Groesster Wert: " +nums[max]); } } 61 Arrays Deklaration eines Arrays: public class MyArray1 { public static void main(String[ ] args) { int a1 [ ]= {1,2,3,4,5}; // Definition von a1 int a2[ ]; // Deklaration von a2; for (int i = 0; i < a1.length; i++) System.out.println(a1[i]); for (int i = 0; i < a2.length; i++) System.out.println(a2[i]); } } • Ergibt einen Fehler, da a2 nicht initialisiert wurde Zuweisung von Arrays: public class MyArray1 { public static void main(String[ ] args) { int a1[ ]= {1,2,3,4,5}; // Definition von a1 int a2[ ]; // Deklaration von a2; a2 = a1; // Zuweisung von a1 an a2 for(int i = 0; i < a1.length; i++) System.out.println(a1[i]); for (int i = 0; i < a2.length; i++) System.out.println(a2[i]); } } 62 Arrays Kopieren von Arrays (by reference): public class ArrayCopy { public static void main(String[ ] args) { int[ ] a = {1,2,4,8,16}; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print (a[i]+" "); System.out.println(); int[ ] b = {32,64,128,256,512,1024}; System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); a=b; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print(a[i]+" "); System.out.println(); a[0]=33; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print (a[i]+" "); System.out.println(); System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); } } Ausgabe: a: 1 2 4 8 16 b: 32 64 128 256 512 1024 a: 32 64 128 256 512 1024 a: 33 64 128 256 512 1024 b: 33 64 128 256 512 1024 63 Arrays Referenzdatentypen • Die komplexeren Datentypen von Java sind Objekte und Arrays. Sie werden als „Referenztypen“ bezeichnet, weil sie „per Referenz“ (byreference) verarbeitet werden • Im Gegensatz dazu werden die einfachen Datentypen by value, also „per Wert“ verarbeitet. Kopieren von Variablen (by value): public class VarCopy { public static void main(String[] args) { int a = 1; System.out.println("a: "+a); int b = 2; System.out.println("b: "+b); a=b; System.out.println("a: "+a); System.out.println("b: "+b); a=3; System.out.println("a: "+a); System.out.println("b: "+b); } } Ausgabe: a: 1 b: 2 a: 2 b: 2 a: 3 b: 2 64 Arrays Kopieren von Arrays (by value): public class ArrayCopy { public static void main(String[ ] args) { int[ ] a = {1,2,4,8,16}; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print (a[i]+" "); System.out.println(); int[ ] b = {32,64,128,256,512,1024}; System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); System.arraycopy(a,0,b,0,a.length); System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print(a[i]+" "); System.out.println(); System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); a[0]=33; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print (a[i]+" "); System.out.println(); System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); } } Ausgabe: a: 1 2 4 8 16 b: 32 64 128 256 512 1024 a: 1 2 4 8 16 b: 1 2 4 8 16 1024 a: 33 2 4 8 16 b: 1 2 4 8 16 1024 65 Arrays Vorsicht vor Überschreitung der Arraygrenzen: public class ArrayCopy { public static void main(String[ ] args) { int[ ] a = {1,2,4,8,16}; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print (a[i]+" "); System.out.println(); int[ ] b = {32,64,128,256,512,1024}; System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); System.arraycopy(a,0,b,b.length,a.length); System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print(a[i]+" "); System.out.println(); System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); a[0]=33; System.out.print("a: "); for (int i = 0; i < a.length; i++) System.out.print (a[i]+" "); System.out.println(); System.out.print("b: "); for (int i = 0; i < b.length; i++) System.out.print(b[i]+" "); System.out.println(); } } Keine Erweiterung eines bestehenden Arrays möglich! Lösung: int c[ ] = new int [a.length + b.length] System.arraycopy(a,0,c,0,a.length); System.arraycopy(b,0,c,a.length,b.length); 66 Arrays Mehrdimensionale Arrays (Felder) byte ZweiDimArray[ ][ ]; • Deklaration der Variablen ZweiDimArray mit Typ byte[][] (Array-vonArray-aus-byte). byte ZweiDimArray[ ][ ] = new Byte [256][ ]; • Dynamische Bereitstellung eines Arrays mit 256 Elementen. Jedes Element dieses neuen Arrays ist vom Typ byte[] - einem eindimensionalen Array von bytes byte ZweiDimArray[][] = new Byte [256][16]; • Dynamische Bereitstellung eines 256Bytes-Arrays, von denen jeder 16 Bytes aufnehmen kann. Gleichzeitig wird eine Referenz dieser 16 byteArrays in den 256 Elementen des „äußeren“ Arrays gespeichert. Die 16 Bytes dieser 256 Arrays werden mit dem Standardwert 0 initialisiert. Nicht Erlaubt: byte ZweiDimArray[ ][ ] = new Byte [ ][16]; 67 Arrays Erlaubt: Beliebige Dimension eines mehrdimensionalen Arrays: int[ ][ ][ ][ ][ ] FuenfDim=new int[3][4][5][6][7]; • Nicht rechteckige Form von Arrays: int ZweiDim[ ][ ]= {{1,2},{3,4,5}, {5,6,7,8}}; Beispiel: (Generieren einer Matrix und Ausgabe der Matrix) public class Matrix { public static void main(String[] args) { int matrix[][]=new int[4][5]; //Ausgabe der Matrix for(int i = 0; i < matrix.length; i++) { for (int j=0;j<matrix[i].length; j++) System.out.print (matrix[i][j] +" "); System.out.println(); } } } Ausgabe: 0 0 0 0 0 00000 00000 00000 68 Arrays Beispiel: Generieren der Einheitsmatrix und Ausgabe der Einheitsmatrix public class EinheitsMatrix { public static void main(String[ ] args) { int matrix[][]=new int[10][10]; //Generieren der Einheitsmatrix for (int i = 0; i < matrix.length; i++) for (int j=0;j<matrix[i].length; j++) if (i==j) matrix[i][j] =1; //Ausgabe der Matrix for(int i = 0; i < matrix.length; i++) { for (int j=0;j<matrix[i].length; j++) System.out.print (matrix[i][j] +" "); System.out.println(); } } } Ausgabe: 1 0 0 0 0 0 0 0 0 0 0100000000 0010000000 0001000000 0000100000 0000010000 0000001000 0000000100 0000000010 0000000001 69 Arrays Beispiel: Nicht rechteckige Form eines mehrdimensionalen Arrays public class Array2 { public static void main(String[ ] args) { short triangle[][]=new short[10][]; for (int i=0; i < triangle.length;i++) { triangle[i] = new short[i+1]; for (int j=0;j<i+1; j++) triangle[i][j] = (short) (i+j); } for(int i = 0; i < triangle.length; i++) { for (int j=0;j<triangle[i].length; j++) System.out.print (triangle[i][j] +" "); System.out.println(); } } } Ausgabe: 0 12 234 3456 45678 5 6 7 8 9 10 6 7 8 9 10 11 12 7 8 9 10 11 12 13 14 8 9 10 11 12 13 14 15 16 9 10 11 12 13 14 15 16 17 18 70 Arrays • Feste Anzahl von Komponenten • Beliebiger, aber für alle Komponenten gleicher Typ • Die Komponenten sind linear geordnet • Auf die einzelnen Komponenten kann direkt zugegriffen werden • Mehrdimensionale Arrays • Arrays sind Objekte. Dennoch gibt es Unterschiede zu »normalen« Objekten • Gemeinsamkeiten von Objekten und Arrays: • – Arrays werden wie Objekte grundsätzlich dynamisch angelegt und am Ende ihrer Verwendung automatisch vom Garbage Collector entfernt – Arrays sind wie Objekte Referenztypen – Arrays sind wie alle Klassen implizit Unterklassen der Klasse Object Array-Elemente werden wie die Datenelemente von Objekten auch stets automatisch initialisiert. Unterschiede von Objekten und Arrays: – Arrays haben keine Konstruktoren. Statt dessen gibt es für Arrays eine spezielle Syntax des new-Operators – Keine Unterklassen von Arrays möglich. 71 Arrays Beispiel: Sortieren eines Feldes public class ArraySortMain { public static void main(String[ ] args) { int [ ] nums = new int[10]; //Arrayerzeugung //Zufallszahlen generieren for(int i = 0; i < nums.length; i++) nums[i] = (int) (Math.random() * 10); //Ausdruck des erzeugten Arrays for(int i = 0; i < nums.length; i++) System.out.print(nums[i]+“ „); System.out.println(); // Jetzt kommt das Sortieren for (int i = 0; i < nums.length; i++) { int min = i; //Suchen des kleinsten Elementes zwischen i //und dem Ende des Arrays. for (int j = i; j < nums.length; j++) if (nums[j] < nums[min]) min = j; // Tauschen des kleinsten Elementes mit i int tmp; tmp = nums[i]; nums[i] = nums[min]; nums[min] = tmp; //Ausdruck des Feldes, bei jedem Sortierdurchlauf for (int j = 0; j < nums.length; j++) System.out.print(nums[j]+“ „); System.out.println(); } } } 72 Arrays Beispiel: Sortieren eines Feldes public class ArraySortMeth { public static int[ ] einlesen() { int [ ] nums = new int[10]; for(int i = 0; i < nums.length; i++) nums[i] = (int) (Math.random() * 10); for(int i = 0; i < nums.length; i++) System.out.print(nums[i]+“ „); System.out.println(); return nums; } public static void sort(int[ ] nums) { for (int i = 0; i < nums.length; i++) { int min = i; for (int j = i; j < nums.length; j++) if (nums[j] < nums[min]) min = j; int tmp; tmp = nums[i]; nums[i] = nums[min]; nums[min] = tmp; } } public static void main(String[] args) { int[ ] nummer=einlesen(); sort(nummer); for(int i = 0; i < nummer.length; i++) System.out.print(nummer[i]+“ „); System.out.println(); } } 73 Arrays Beispiel: Sortieren eines Feldes public class ArraySortMethViele { public static int[ ] einlesen() { int [ ] nums = new int[10]; for (int i = 0; i < nums.length; i++) nums[i] = (int) (Math.random() * 10); for (int i = 0; i < nums.length; i++) System.out.print(nums[i]+“ „); System.out.println(); return nums; } public static void ausgabe (int[ ] nums) { for (int i = 0; i < nums.length; i++) System.out.print(nums[i]+“ „); System.out.println(); } public static void sort(int[ ] nums) { for (int i = 0; i < nums.length; i++) { int min = i; for (int j = i; j < nums.length; j++) if (nums[j] < nums[min]) min = j; int tmp; tmp = nums[i]; nums[i] = nums[min]; nums[min] = tmp; } } public static void main(String[] args) { int[ ] nummer=einlesen(); sort(nummer); ausgabe(nummer); } } 74 Arrays Beispiel: Sortieren eines Feldes public class ArraySortMethViele { public static int[] einlesen() { int [ ] nums = new int[10]; for (int i = 0; i < nums.length; i++) nums[i] = (int) (Math.random() * 10); for (int i = 0; i < nums.length; i++) System.out.print(nums[i]+“ „); System.out.println(); return nums; } public static void ausgabe(int[ ] nums) { for (int i = 0; i < nums.length; i++) System.out.print(nums[i]+“ „); System.out.println(); } public static void sort(int[ ] nums) { for (int i = 0; i < nums.length; i++) { int min = i; for (int j = i; j < nums.length; j++) if (nums[j] < nums[min]) min = j; int tmp; tmp = nums[i]; nums[i] = nums[min]; nums[min] = tmp; } } public static void main(String[] args) { int[ ] nummer=einlesen(); sort(nummer); ausgabe(nummer); } } 75 Klassen und Objekte Objektorientierte Softwareentwicklung Was ist Objektorientierung ? Oberflächlich betrachtet bedeutet der Begriff "objektorientiert", daß wir Software als eine Ansammlung diskreter Objekte betrachten, die sowohl Datenstruktur als auch Verhalten in sich vereinen. Dies steht im Gegensatz zur konventionellen Programmierung, bei der Datenstruktur und Verhalten nur lose miteinander verbunden sind. Es ist nicht ganz unstrittig, welche Eigenschaften ein objektorientierter Ansatz genau erfordert. Im allg. gehören jedoch vier Aspekte dazu: Identität, Klassifikation, Polymorphismus und Vererbung 76 Klassen und Objekte Eigenschaften von Objekten Identität heißt, daß Daten mit diskreten, unterscheidbaren Entitäten Objekte zugeordnet werden. Ein Absatz in einem Dokument, ein Fenster auf einer Workstation und die weiße Dame in einem Schachspiel sind Beispiele für Objekte. Jedes Objekt besitzt eine eigene inhärente ("ihm innenwohnende") Identität. Mit anderen Worten, zwei Objekte sind klar voneinander unterscheidbar, selbst wenn alle ihre Attributwerte (wie Name oder Größe) identisch sind. Klassifikation bedeutet, daß Objekte mit der gleichen Datenstruktur (Attribute) und dem gleichen Verhalten (Operationen) zu einer Klasse gruppiert werden. Eine Klasse ist eine Abstraktion, die die Eigenschaften beschreibt, die für eine Anwendung wichtig sind, und den Rest ignoriert. Die Wahl von Klassen ist immer beliebig und hängt von der Anwendung ab. Jede Klasse beschreibt eine möglicherweise unendliche Menge individueller Objekte. Jedes Objekt wird als eine Instanz seiner Klasse bezeichnet. Jede Instanz der Klasse besitzt eigene Werte für alle ihre Attribute, während sie die Attributnamen und Operationen mit anderen Instanzen der Klasse teilt. Ein Objekt enthält eine implizite Referenz auf seine eigene Klasse, so daß es "weiß", welcher Klasse es angehört. Polymorphismus bedeutet, daß sich die gleiche Operation in unterschiedlichen Klassen unterschiedlich verhalten kann. Das Verhalten der Operation verschieben zum Beispiele ist in der Klasse Fenster ein anderes als in der Klasse Schachfigur. Eine Operation ist eine Aktion oder Transformation, die ein Objekt ausführt bzw. die auf dem Objekt ausgeführt wird. Rechtsbündig ausrichten, anzeigen und verschieben sind Beispiele für Operationen. Eine spezifische Implementierung einer Operation innerhalb einer bestimmten Klasse heißt Methode. Weil ein objektorientierter Operator polymorph ist, kann es mehr als eine Methode geben, die ihn implementiert. Vererbung bezeichnet die gemeinsame Verwendung von Methoden und Operationen durch verschiedene Klassen auf der Basis einer hierarchischen Relation. Eine Klasse kann sehr allgemein definiert sein und dann in immer detaillierteren Unterklassen verfeinert werden. Jede Unterklasse übernimmt oder erbt alle Eigenschaften ihrer Oberklasse und fügt ihre eigenen individuellen Eigenschaften hinzu. Die Eigenschaften der Oberklasse müssen nicht in jeder Unterklasse wiederholt werden. 77 Klassen und Objekte Begriffe und Paradigmen der objektorientierten Technologie Abstraktion: Eine geistige Fähigkeit des Menschen, Probleme der realen Welt mehr oder weniger detailliert zu betrachten, je nach dem aktuellen Kontext des Problems. Kapselung: (Information Hiding) Eine Modellierungs- und Implementierungstechnik, die die externen Aspekte eines Objekts von den internen Implementierungsdetails des Objekts trennt Vererbung: (Inheritance) Ein objektorientierter Mechanismus, der es ermöglicht, daß Klassen Attribute und Operationen gemeinsam nutzen. Basiert auf einer Relation, meistens auf Generalisierung. Einfachvererbung: Eine Art von Vererbung, bei der eine Klasse nur eine einzige Oberklasse haben kann. Mehrfachvererbung: Eine Art von Vererbung, die es ermöglicht, daß eine Klasse mehr als eine Oberklasse besitzt und Merkmale von allen Vorfahrenklassen erbt. Polymorphismus: Nimmt unterschiedliche Formen an; die Eigenschaft, daß eine Operation sich auf unterschiedlichen Klassen unterschiedlich verhalten kann. Klassifikation: Eine Gruppierung von Objekten mit der gleichen Datenstruktur und dem gleichen Verhalten. Persistente Daten: Daten, die die Ausführung eines bestimmten Programms überdauern. Objektmodellierung: Es existieren verschiedene Arten der Modellierung von Objekten: UML (Unified Modeling Language), OMT (Object Modeling Technique), Booch, Coad-Yourdon, etc.). 78 Klassen und Objekte Prinzip der objektorientierten Programmierung • Ein Gesamtprogramm besteht aus vielen unabhängigen Komponenten (Objekten), die je eine bestimmte Rolle im Programm spielen und die miteinander auf vorgegebene Weise (Methoden) sprechen. Klassen, Objekte und Instanzen • Eine Klasse ist eine Sammlung aller Eigenschaften und Methoden der Objekte dieser Klasse und legt fest, wie diese zu erzeugen sind (Konstruktoren) • Eine Instanz einer Klasse ist ein anderes Wort für ein tatsächliches Objekt. Während Klassen eine abstrakte Darstellung eines Objekts sind, ist eine Instanz dessen konkrete Darstellung • Jede Klasse besteht im allgemeinen aus zwei Komponenten: Eigenschaften und Methoden • Eigenschaften werden durch Variablen definiert (Instanzvariablen und Klassenvariablen) • Methoden bestimmen, was Objekte alles machen können und was man mit Objekten machen kann. Methoden sind Funktionen, die innerhalb von Klassen definiert (Instanzmethoden und Klassenmethoden). 79 Klassen und Objekte Klassen und Objekte in Java Beispiel: public class Circle { private double x,y,r;//Instanzvariablen ´ // Die Konstruktormethode public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; } public double circumference() { return 2 * 3.14159 * r; } public double area() { return 3.14159 * r*r; } public static void main(String[ ] args) { Circle c1 = new Circle(1,1,2); Circle c2 = new Circle(2,2,4); System.out.println(„Flaeche c1: „ + c1.area()); System.out.println(„Flaeche c2: „ + c2.area()); System.out.println(„Umfang c1: „ + c1.circumference()); System.out.println(„Umfang c2: „ + c2.circumference()); } } 80 Klassen und Objekte Objekte und Instanzen: Circle c; // Variable der // Circle-Klasse c = new Circle(1,1,2); // Dynamisch erzeugte Instanz eines Circle-Objektes Zugriff auf Objektdaten: c.x = 2.0; c.y = 2.0; c.r = 1.0; // Initialisiere den Kreis mit // Mittelpunkt (2,2) und // Radius 1.0 Verwendung von Objektmethoden: Circle c = new Circle(); double a; c.r = 2.5; a = c.area(); Beachte: Es wird nicht a = area(c); verwendet, sondern a = c.area(); Objekterzeugung: Circle c = new Circle(); // Konstruktor 81 Klassen und Objekte Konstruktoren: Circle c = new Circle(1.414, -1.0, .25); Der Name des Konstruktors ist immer mit dem Namen der Klasse identisch Der Rückgabewert ist implizit eine Instanz der Klasse. Mehrere Konstruktoren: public class Circle { public double x,y,r; // Mittelpunkt + Radius // Die Konstruktormethoden public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r;} public Circle(double r) { x = 0; y = 0; this.r = r;} public Circle(Circle c) { x = c.x; y = c.y; r = c.r;} public Circle() { x = 0; y = 0; r = 1;} // Methoden für Umfang und Fläche des Kreises public double circumference() { return 2 * 3.14159 * r; } public double area() {return 3.14159 * r*r; } } 82 Klassen und Objekte Kopieren von Objekten (by reference): public class Circle { public double x,y,r; // Instanzvariablen // Die Konstruktormethoden public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r;} public Circle(double r) {this(0.0,0.0,r);} public Circle(Circle c) {this (c.x,c.y,c.r);} public Circle(){this(0.0,0.0,1.0);} public double circumference() { return 2 * 3.14159 * r; } public double area() {return 3.14159 * r*r; } public static void main(String[] args) { Circle c1 = new Circle(); Circle c2 = new Circle(2,2,4); System.out.println("Area c1: " + c1.area()); System.out.println("Area c2: " + c2.area()); c2=c1; System.out.println("Area c1: " + c1.area()); System.out.println("Area c2: " + c2.area()); c1.r=2; System.out.println("Area c1: " + c1.area()); System.out.println("Area c2: " + c2.area()); } } Ausgabe: Area c1: 3.14159 Area c2: 50.26544 Area c1: 3.14159 Area c2: 3.14159 Area c1: 12.56636 Area c2: 12.56636 83 Klassen und Objekte Klassenvariablen: public class Circle { static int num_circles=0; //Klassenvariable: //wie viele Kreise wurden erzeugt? public double x,y,r; // Instanzvariablen // Die Konstruktormethoden public Circle(double x, double y, double r) { this.x = x; this.y = y; this.r = r; num_circles++;} public Circle(double r) {this(0.0,0.0,r);} public Circle(Circle c) {this (c.x,c.y,c.r);} public Circle(){this(0.0,0.0,1.0);} public double circumference() { return 2 * 3.14159 * r; } public double area() {return 3.14159 * r*r; } } Zugriff auf Klassenvariablen: System.out.println(“Kreise: “ + Circle.num_circles); Konstanten: public class Circle { public static final double PI=3.14159265; public double x,y,r; // ... etc. } 84 Klassen und Objekte Klassenmethoden: public class Circle { public double x,y,r; // Liegt der Punkt (a,b) innerhalb des Kreises public boolean isInside(double a, double b) { double dx = a - x; double dy = b - y; double distance = Math.sqrt(dx*dx+dy*dy); if (distance<r) return true; else return false; } // ... etc. } Math.sqrt() ist ein Aufruf einer Klassenmethode (oder statischen Methode), die in Math definiert ist. Sie unterscheidet sich wesentlich von den Instanzmethoden (wie z.B. area() in Circle). 85 Klassen und Objekte Eine Klassenmethode für Kreise: public class Circle { public double x,y,r; // Instanzmethode. Liefert den größeren Kreis public Circle bigger (Circle c) { if (c.r > r) return c; else return this;} // Klassenmethode. Liefert den größeren Kreis public static Circle bigger (Circle a, Circle b) { if (a.r > b.r) return a; else return b; } // ... etc. } Aufruf der Instanzmethode: Circle a = new Circle (2.0); Circle b = new Circle (3.0); Circle c = a.bigger(b); // oder b.bigger(a); Aufruf der Klassenmethode: Circle a = new Circle (2.0); Circle b = new Circle (3.0); Circle c = Circle.bigger(a,b); // oder b.bigger(a); 86 Klassen und Objekte Beispiele zu Klassen Beispiel 1: class Fahrzeug { String marke; String modell; float preis; float gewicht; Fahrzeug (String mar, String mod, float pre, float gew) { this.marke = mar; this.modell = mod; this.preis = pre; this.gewicht = gew; } public String toString () { return „Fahrzeug der Marke „ + marke + „, Modell „ + modell + „, Gewicht „ + gewicht + „ kg“; } public static void main (String args[]) { Fahrzeug ente = new Fahrzeug („Citroen“,“2CV“,8399.90f, 680.5f); System.out.println(„Mein Auto: „+ ente); } } 87 Klassen und Objekte Beispiele zu Klassen Beispiel 2: public class Bruch { long z,n; Bruch (long z, long n) { this.z=z; this.n = n; this.kuerzen(); } public Bruch add(Bruch b) { long z1 = this.z * b.n; long n = this.n * b.n; long z2 = b.z * this.n; return new Bruch(z1 + z2, n); } public Bruch add(long z) { long z1 = this.z; long n = this.n; long z2 = z * this.n; return new Bruch(z1 + z2, n); } public Bruch kuerzen() { long limit = Math.min(z,n) / 2; while (z % 2 == 0 && n % 2 == 0) { this.z = this.z/2; this.n = this.n/2; } 88 Klassen und Objekte Beispiele zu Klassen for (long i = 3; i <= limit; i+=2) { while (z % i == 0 && n % i == 0) { this.z = this.z/i; this.n = this.n/i; } } return this; } public String toString() { if (n == 1) return Long.toString(z); else return z + „/“ + n; } } public class MyBruch { public static void main(String args[ ]) { Bruch z1 = new Bruch(1,2); System.out.println(„z1 = „ + z1); Bruch z2 = new Bruch(10, 16); System.out.println(„z2 = „ + z2); Bruch z3 = new Bruch(3,8); System.out.println(„z3 = „ + z3); System.out.println(„z4 = „ + z3.add(z2)); System.out.println(„z6 = „ + z3.add(5L)); System.out.println(„z5 = „ + new Bruch(128, 256)); } } 89 Aufgaben Aufgaben zu Klassen Aufgabe 1 Schreibe eine Klasse, die die komplexen Zahlen repräsentiert. 1. 2. Erstelle einen oder mehrere geeignete Konstruktoren zur Instanziierung von komplexen Zahlen Erstelle Instanzenmethoden für folgende Operationen: – Stringdarstellung einer komplexen Zahl. – Addition/Subtraktion zweier komplexer Zahlen. Das Ergebnis ist eine neue komlexe Zahl – Multiplikation zweier komplexer Zahlen. Das Ergebnis ist eine neue komlexe Zahl. Aufgabe 2 Schreibe eine Klasse, die Polynome 2. Grades repräsentiert. Ein Polynom d ieser Klasse hat allgemein das folgende Aussehen: ax² + bx + c 1. 2. Erstelle einen oder mehrere geeignete Konstruktoren zur Instanziierung von Polynomen 2. Grades Erstelle Instanzenmethoden für folgende Operationen: – – – – – Stringdarstellung eines Polynoms Berechnen des Funktionswertes eines Polynoms Addition/Subtraktion zweier Polynome. Das Ergebnis ist ein neues Polynom Multiplikation mit einem Skalar. Das Ergebnis ist ein neues Polynom. Berechnung der Nullstellen des Polynoms. 90 Vererbung von Klassen Vererbung Motivation Beispiel: Benutzerverwaltung (z.B. im Rechenzentrum) mit mehreren Kategorien von Benutzern. Studenten, Mitarbeiter und externe Personen. Für Personen aus den verschiedenen Gruppen werden unterschiedliche Informationen erhoben. Beispiel Benutzergruppen: externer Benutzer Person class Person { int userId; String name; String telNr; Person(int id, String name, String tel) { this.userId = id; this.name = name; this.telNr = tel; } } Beispiel Benutzergruppen: Student class Student { int userId; String name; String telNr; String matrNr; Student(int id, String name, String tel, String matrNr) { this.userId = id; this.name = name; this.telNr = tel; this.matrNr = matrNr; } } 91 Vererbung von Klassen Beispiel Benutzergruppen: Mitarbeiter class Mitarbeiter { int userId; String name; String telNr; String dienstgrad; Mitarbeiter(int id, String name, String tel, String grad) { this.userId = id; this.name = name; this.telNr = tel; this.dienstgrad = grad; } } Frage: Können wir alle drei Benutzergruppen in einem einzigen Feld gemeinsam verwalten? Einfache Antwort: Nein, denn es handelt sich um drei verschiedene Klassen; die Objekte haben verschiedenenTyp. Komplizierte Antwort: Doch, wir können die Objekte in einem einzigen Feld speichern, wenn wir die Gemeinsamkeitender drei Klassen extrahieren! Beobachtung: Die gemeinsame Information von Studenten und Mitarbeitern ist die Information, die für Personen gespeichert wird. 92 Vererbung von Klassen Vererbung: Grundprinzip Student und Mitarbeiter erben diese Attribute von Person; alles was man mit einer Instanz der Klasse Person machen kann, kann man auch mit einer Instanz der Klassen Mitarbeiter und Student machen! 93 Vererbung von Klassen Vererbung: Grundprinzip 94 Vererbung von Klassen Vererbung in Java class Person { int userId; String name; String telNr; Person( ){ } Person(int id, String name, String tel) { this.userId = id; this.name = name; this.telNr = tel; } } Die Klasse Person wird fast wie gehabt definiert. Aus einem Grund, den wir später noch kennen lernen werden, benötigen wir im Augenblick noch den Standardkonstruktor. class Student extends Person { String matrNr; Student(int id, String name, String tel, String matrNr) { this.userId = id; this.name = name; this.telNr = tel; this.matrNr = matrNr; } } extends besagt, daß die Klasse Student von der Klasse Person erbt. Weil die Klasse Student von der Klasse Person erbt, besitzt die Klasse Student alle Attribute der Klasse Person (ohne daß die Attribute explizit definiert sind). 95 Vererbung von Klassen class Mitarbeiter extends Person { String dienstgrad; Mitarbeiter(int id, String name, String tel, String grad) { this.userId = id; this.name = name; this.telNr = tel; this.dienstgrad = grad; } } extends besagt, daß die Klasse Mitarbeiter von der Klasse Person erbt. Weil die Klasse Mitarbeiter von der Klasse Person erbt, besitzt die Klasse Mitarbeiter alle Attribute der Klasse Person (ohne daß die Attribute explizit definiert sind). Bemerkung: Die neuen Definitionen sind im wesentlichen identisch mit den alten separaten der Definitionen der Klassen. Der einzige Unterschied: Jetzt können Objekte der Klasse Student und Mitarbeiter an eine Variable des Typs Person zugewiesen werden, da sie diese Klasse spezialisieren! Person[ ] pers = new Person[3]; pers[0] = new Mitarbeiter(1,"Huber","(030) ...","WiMi"); pers[1] = new Student(2,"Meier", "(08421) 4711","0815"); pers[2] = new Person(5,"Mueller","(08421) 461"); 96 Vererbung von Klassen Beispiel: Person[ ] pers = new Person[3]; pers[0] = new Mitarbeiter(1,"Huber", "(030) ...", "WiMi"); pers[1] = new Student(2,"Meier", "(08421) 4711", "0815"); pers[2] = new Person(5,"Mueller", "(08421) 461"); // Ausgabe aller Adressen des Arrays pers: for (int i = 0; i < pers.length; i++) { System.out.println(pers[i].name + ":" + pers[i].telNr); } Das Prinzip: • • Ein Objekt einer Klasse B, die von Klasse A abgeleitet ist (von A erbt), besitzt zusätzlich zu den in der Klasse B definierten Attributen und Methoden alle Attribute und Methoden der Klasse A. Ein Objekt einer Klasse B kann an eine Variable der Klasse A zugewiesen werden, wenn Klasse B von Klasse A abgeleitet ist. Beispiel: Person pers; pers = new Mitarbeiter(1,"Huber", "(030) ...", "WiMi"); • Die umgekehrte Richtung ist nicht zulässig! Gegenbesipiel: Mitarbeiter marb; marb = new Person(1,"Huber", "(030) ..."); • • Ein Objekt, das in einer Variablen der Klasse A gespeichert ist, kann ein Objekt jeder Klasse B sein, die von A erbt. Für ein in einer Variablen der Klasse A gespeichertes Objekt können alle Attribute und Methoden der Klasse A benutzt werden —und nur diese! Selbst dann, wenn es sich um ein Objekt der Klasse B handelt, das mehr Attribute besitzt. 97 Vererbung von Klassen Beispiel: Person pers; pers = Mitarbeiter(1,"Huber", "(030) ...", "WiMi"); System.out.println(pers.name + ":" + pers.telNr); System.out.println(pers.dienstgrad); Das Objekt, das in pers gespeichert ist, hat zwar ein Attribut dienstgrad, aber die Variable pers hat nur den Typ Person! Da die Klasse Person selbst kein Attribut dienstgrad besitzt, dürfen wir es nicht benutzen. Bei starker Typisierung wird die Korrektheit eines Zugriffs anhand des Variablentyps geprüft! 98 Vererbung von Klassen Vererbungshierarchie Beamter erbt indirekt über Mitarbeiter alle Eigenschaften von Person! Ein Objekt der Klasse Beamter kann also sowohl einer Variablen vom Typ Mitarbeiter als auch einer Variablen vom Typ Person zugewiesen werden. class Beamter extends Mitarbeiter { String besGr; ... } 99 Vererbung von Klassen Vererbung von Methoden Methoden werden ebenso vererbt wie Attribute! class Person { int userId; String name; String telNr; Person() { } Person(int id, String name, String tel) { \* wie gehabt *\} public String toString() { return name + ": " + telNr} } Person pers = new Person(5,"Mueller", "(08421) 461"); Person pers = new Person(6,"Maier", "(08421) 462"); System.out.println(pers.toString()); System.out.println(pers); Ausgabe am Bildschirm: Mueller: (08421) 461 Maier: (08421) 462 Mitarbeiter marb; marb = Mitarbeiter(1,"Huber", "(030) ...", "WiMi"); System.out.println(marb); Ausgabe am Bildschirm: Huber: (030) ... Da Mitarbeiter von Person erbt, besitzt jedes Objekt der Klasse Mitarbeiter auch die Methode toString. 100 Vererbung von Klassen Überschreiben von Methoden Bisher: In den abgeleiteten Klassen wurden neue Attribute oder neue Methoden hinzugefügt. Jetzt: In der abgeleiteten Klasse werden Methoden der ursprünglichen Klasse überschrieben. Beispiel: class Mitarbeiter extends Person { String dienstgrad; Mitarbeiter(int id, String name, String tel, String grad) { \* wie gehabt *\ } public String toString() { return name + ":" + tel +","+dienstgrad;} } class Student extends Person { String matrNr; Student(int id, String name, String tel, String matrNr) { /* wie gehabt */ } public String toString() { return name + ":" + tel + ", " + matrNr; } } 101 Vererbung von Klassen Person[ ] pers = new Person[3]; pers[0] = new Mitarbeiter(1,"Huber", "(030) ...", "WiMi"); pers[1] = new Student(2,"Meier", "(08421) 4711", "0815"); pers[2] = new Person(5,"Mueller", "(08421) 461"); for (int i = 0; i < pers.length; i++) { System.out.println(pers[i]); } /* Ausgabe am Bildschirm: * Huber: (030) ..., WiMi * Meier: (08421) 4711, 0815 * Mueller: (08421) 461 */ Hier wurden offensichtlich die neuen toString-Methoden der Klassen Mitarbeiter und Student aufgerufen. 102 Vererbung von Klassen Eine Unterklassenbeziehung läßt sich explizit in der folgenden Form angeben: class Unterklasse extends Oberklasse { .... } Die Unterklasse enthält alle Komponenten der Oberklasse. Erweiterbar um neue Komponenten Unterklasse ist Spezialfall der Oberklasse Komponenten der Oberklasse sind von der Unterklasse aus mit dem Schlüsselwort super erreichbar. Dies gilt auch für den Aufruf des Konstruktors derOberklasse. Klassen, für die keine Beziehung zu anderen Klassenfest gelegt wurde, sind automatisch Unterklassen der Klasse Object. 103 Vererbung von Klassen Beispiel: „Chefs sind auch Personen“ class Person { String Name; String Vorname; int PersonalNummer; Person (String Name, String Vorname, int PersonalNummer) { this.Name = Name; this.Vorname = Vorname; this.PersonalNummer = PersonalNummer; } void print() { System.out.println("Name: "+ this.Name); System.out.println("Vorname: "+ this.Vorname); System.out.println("Personalnummer: "+ this.PersonalNummer); } } class Chef extends Person { String Abteilung; //Zusaetzliches Attribut Chef (String Name, String Vorname, int PersonalNummer, String Abteilung) { super(Name,Vorname,PersonalNummer); this.Abteilung=Abteilung; } // Ueberschreibt die Methode print() in Person void print() { super.print(); System.out.println("Leiter der Abteilung: "+ this.Abteilung); } } 104 Vererbung von Klassen Beispiel: Verwendung der Klassen Person und Chef public class Firma { public static void main (String args[ ]) { Person personal[] = new Person [4]; personal [0] = new Person („Meier“, „Karl“, 100); personal [1] = new Person („Huber“, „Egon“, 101); personal [2] = new Person („Bauer“, „Hans“, 102); personal [3] = new Chef („Wichtig“, „Willi“, 103,“Einkauf“); for (int i =0; i< personal.length; i++) personal[i].print(); // Polymorphie } } 105 Vererbung von Klassen Beispiel: Klasse Fahrzeug class Fahrzeug { String marke; String modell; float preis; float gewicht; Fahrzeug (String mar, String mod, float pre, float gew) { this.marke = mar; this.modell = mod; this.preis = pre; this.gewicht = gew; } public String toString () { return "Fahrzeug der Marke " + marke + ", Modell " + modell + ", Gewicht " + gewicht + " kg"; } public static void main (String args[ ]) { Fahrzeug ente = new Fahrzeug("Citroen","2CV", 8399.90f, 680.5f); System.out.println("Mein Auto: "+ ente); } } 106 Vererbung von Klassen Beispiel: Erweiterung der Klasse Fahrzeug class Auto extends Fahrzeug { String kraftstoff; int ps; Auto (String mar, String mod, float pre, float gew, String kra, int ps) { super(mar,mod,pre,gew); this.kraftstoff = kra; this.ps = ps; } public String toString () { return super.toString() + ", " + kraftstoff + "-Kraftstoff, " + ps + " ps"; ´ } public static void main (String args[ ]) { Auto ente = new Auto("Citroen","2CV", 8399.90f, 680.5f,"Normal",28); System.out.println("Mein Auto: "+ ente); } } 107 Vererbung von Klassen Objektklasse Object 108 Vererbung von Klassen Vergleich von Objekten • Vergleich von primitiven Datentypen: int i1 = 12; int i2 = 21; int i3 = 12; System.out.println(i1+"=="+i2+ " ? " + (i1==i2)); System.out.println(i1+"=="+i3+ " ? " + (i1==i3)); System.out.println(i2+"=="+i3+ " ? " + (i2==i3)); System.out.println(); • Ausgabe: K:\java-vorlesung\code>java -classpath . Bruch 12==21 ? false 12==12 ? true 21==12 ? false • Vergleich von Objekten: public static void main(String argv[]) { Bruch b1 = new Bruch(13,3); Bruch b2 = new Bruch(3,13); Bruch b3 = new Bruch(13,3); Bruch b4 = b2; System.out.println(b1+"=="+b2+ " ? " + (b1==b2)); System.out.println(b1+"=="+b3+ " ? " + (b1==b3)); System.out.println(b1+"=="+b4+ " ? " + (b1==b4)); System.out.println(b2+"=="+b4+ " ? " + (b2==b4)); System.out.println(); System.out.println(b1+".equals("+b2+")?"+ (b1.equals(b2))); System.out.println(b1+".equals("+b3+")?"+ (b1.equals(b3))); System.out.println(b1+".equals("+b4+")?"+ (b1.equals(b4))); System.out.println(b2+".equals("+b4+")?"+ (b2.equals(b4))); 109 Vererbung von Klassen • Ausgabe: K:\java-vorlesung\code>java -classpath . Bruch 12==21 ? false 12==12 ? true 21==12 ? false 13/3==3/13 ? false 13/3==13/3 ? false 13/3==3/13 ? false 3/13==3/13 ? true 13/3.equals(3/13) ? false 13/3.equals(13/3) ? false 13/3.equals(3/13) ? false 3/13.equals(3/13) ? true • Eigene Methode: public boolean equals(Object o) public boolean equals(Object o) { if (o instanceof Bruch) { Bruch b = (Bruch) o; return this.zaehler == b.zaehler && this.nenner == b.nenner; } else return false; } • Ausgabe: ... 13/3.equals(3/13) ? false 13/3.equals(13/3) ? true 13/3.equals(3/13) ? false 3/13.equals(3/13) ? true 110 Vererbung von Klassen Daten verstecken und kapseln Sichtbarkeitsmodifikatoren: public Klasse, Variable oder Methode überall sichtbar und damit auch überall benutzbar private private-Variable sind nur in den Methoden sichtbar, die in dieser Klasse definiert sind. private-Methoden können nur von Methoden innerhalb der Klasse aufgerufen werden. private-Elemente (members) sind nicht in Subklassen sichtbar und werden auch nicht an Subklassen vererbt. protected protected-Elemente sind in allen Subklassen dieser Klasse sichtbar, und auch in allen Klassen, die mit dieser Klasse in einem Paket enthalten sind. „friendly“ oder „package“ Standardmäßige Paketsichtbarkeit, die verwendet wird, wenn ein Element einer Klasse mit keinem der Schlüsselworte public, private oder protected dekalriert ist. 111 Vererbung von Klassen Erreichbarkeit von Klassenelementen Sichtbarkeit Erreichbar für public protected friendly private Gleiche Klasse Ja Ja Ja Ja Klasse im gleichen Paket Ja Ja Ja Nein Subklasse im anderen Paket Ja Ja Nein Nein Keine Subklasse, anderes Paket Ja Nein Nein nein 112 Aufgaben Aufgaben zu Klassen Aufgabe 1 Schreibe eine Klasse welche Terme der Form ax y repräsentiert. (Beispiel: 2x 4 , 3x 9 , -2x 2 ..). Hierbei können folgende Vereinfachungen vorgenommen werden: a ganzzahlig, y ganzzahlig und >= 0. 1. Erstelle einen oder mehrere geeignete Konstruktoren 2. Erstelle Instanzenmethoden für folgende Operationen: – – – – Stringdarstellung eines Terms Berechnen des Funktionswertes eines Terms Multiplikation zweier Terme. Das Ergebnis ist ein neuer Term Berechnung der Ableitung eines Terms Aufgabe 2 Schreibe eine Klasse welche ein Haushaltsbuch repräsentiert. 1. Erstelle einen oder mehrere geeignete Konstruktoren 2. Erstelle Instanzenmethoden für folgende Operationen: – – – – – Einzahlung mit Kommentar (Bsp: 100 DM von Oma) Auszahlung mit Kommentar. (Bsp: 10 DM für Kino) Abfrage aller Einzahlungen Abfrage aller Ausgaben Abfrage des aktuellen Kontostandes 113 Aufgaben Aufgaben zu Klassen Aufgabe 1 Schreibe eine Klasse zur Repräsentation von Polynomen beliebiger Ordnung. Nutze hierzu die in Aufgabe 2 des vorhergehenden Übungsblattes entwickelte Klasse Term. Bsp: 2x 4 + 3x 3 -2x 2 + 5x -10 1. Erstelle einen oder mehrere geeignete Konstruktoren 2. Erstelle Instanzenmethoden für folgende Operationen: – – – – Stringdarstellung eines Polynoms Berechnen des Funktionswertes an beliebiger Stelle eines Polynoms Addition/Subtraktion zweier Polynome. Das Ergebnis ist ein neues Polynom Berechnung der Ableitung eines Polynoms. Das Ergebnis ist ein neues Polynom. 114 Aufgaben Aufgaben zu Klassen Aufgabe 1 Schreibe ein einfaches Programm zum Speichern von Adressen. Zur Vereinfachung genügt es, wenn nur eine feste Anzahl von Adressen gespeichert werden kann. Aufgabe 2 Der folgende Algorithmus („Siebes von Eratostenes“) ermittelt alle Primzahlen zwischen 2 und einer vorgegebenen Grenze N: 1. SIEB = alle natürlichen Zahlen von 2 bis N 2. Primzahlen = leere Menge 3. wiederhole die Schritte (4) bis (6) solange, bis SIEB leer wird 4. bestimme die kleinste Zahl MIN in SIEB 5. füge MIN zu Primzahlen hinzu 6. entferne MIN und alle seine ganzahligen Vielfachen aus SIEB Schreibe ein Programm, das diesen Algorithmus implementiert. 115 Exceptions Exceptions und ihre Behandlung Exception - Ausnahmebedingung (wie z.B. Fehler) Exception erzeugen (engl. throw) - bedeutet Ausnahmebedingung zu signalisieren Exception abfangen (engl. catch) – bedeutet ein Ausnahmebedingung zu behandeln, d.h. alle Aktionen durchzuführen, die notwendig sind um den normalen Zustand wiederherzustellen Exception-Objekte Eine Exception ist in Java ein Objekt, nämlich eine Instanz irgendeiner Unterklasse von java.lang.Thro-wable. Throwable besitzt 2 Standardunterklassen: • java.lang.Error für Probleme beim dynamischen Laden oder bei Probleme der JVM. Sie werden i.d.R. nicht abgefangen • java,lang,Exception Exceptions dieser Unterklasse weisen auf Bedingungen hin, die abgefangen und behoben werden können, z.B. java.io.EOFException oder java.lang.ArrayAccessOutofBounds. 116 Exceptions Exception-Handling try/catch/finally-Anweisung zum Exception-Handling: • try - stellt eine Codeblock zur Verfügung mit dem Exceptions und abnormale Abbrüche behandelt werden • catch - dem try-Block folgen null oder mehr catch-Klauseln, die bestimmte Exception-Typen abfangen und behandeln • finally - den catch-Klauseln folgt optional ein finally Block, der hinterher „aufräumt“. Die Anweisungen eines finally-Blocks werden garantiert ausgeführt, gleichgültig mit welchem Status der try-Block beendet wird. Beispiel: try { /* Programmcode der Exceptions erzeugt */ } catch ( Typ1 e1) { /* Behandle Exception e1 vom Typ Typ1 */ } catch ( Typ e2 ) { /* Behandle Exception e2 vom Typ Typ2 */ } finally { /* Dieser Code wird immer ausgeführt */ } 117 Exceptions Beispiel: public class ExceptionMethods { public static void main(String[ ] args) { try { throw new Exception („Meine Exception“); } catch ( Exception e) { System.out.println(„Exception gefangen“); System.out.println(„e.getMessage(): „+ e.getMessage()); } } } Ausgabe: Exception gefangen e.getMessage(): Meine Exception Einige Methoden von Throwable: String getMessage() Gibt die Beschreibung der Exception zurück. String to String() Gibt eine kurze Beschreibung von Throwable einschließlich der detailierten Beschreibung. System.out.println(e.toString()); Ausgabe: java.lang.Exception: Meine Exception void printStackTrace() Gibt Throwable unbd den Call Stack Trace zurück. e.printStackTrace(); Ausgabe: java.lang.Exception: Meine Exception at ExceptionMethods.main 118 Exceptions Exceptions deklarieren Java erfordert, daß jede Methode, die eine Exception verursachen kann, diese entweder abfangen oder in der Methodendeklaration den Typ der Exception mit einer throwsKlausel abgeben muß. Beispiel: public void open_file() throws IOException { /* Hier stehen Anweisungen, die eine nicht abgefangene java.io.IOException veruraschen können. */ } public void myfunc () throws tooBig, tooSmall, divZero{ /* Hierbei entstehen die Exceptions tooBig, tooSmall, divZero die nicht abgefangen werden. */ } Eigene Exceptions definieren und erzeugen Neben den Standard Java Exception (Klasse Throwable mit Unterklassen Error und Exception, siehe java.sun.com) können auch eigene Exceptions definiert werden. 119 Exceptions Beispiel: class MyException extends Exception{ public MyException () {} public MyException (String msg) { super (msg); } } public class Inheriting { public static void f() throws MyException { System.out.println(„Throwing MyException from f()“); throw new MyException(); } public static void g() throws MyException { System.out.println(„Throwing MyException from g()“); throw new MyException(„originated in g()“); } public static void main(String[] args) { try { f(); } catch ( MyException e) { e.printStackTrace() } try { g(); } catch ( MyException e) { e.printStackTrace() } } } 120 Exceptions Ausgabe: Throwing MyException from f() My Exception at Inheriting.f (Inheriting.java:16) at Inheriting.main (Inheriting.java:24) Throwing MyException from g() My Exception: originated in g() at Inheriting.f (Inheriting.java:20) at Inheriting.main (Inheriting.java:29) 121 Exceptions Exception Matching Der Exception-Handler sucht in den catch-Klauseln, die erste die „paßt“. Matching einer Exception erfordert kein genaues „passen“ . Ein Objekt einer erweiterten Klasse wird auch von einer catch-Klausel der Basis-Klasse gefangen: Beispiel: class Annoyance extends Exception{} class Sneeze extends Annoyance{} public class Human () { public static void main(String[] args) { try { throw new Sneeze(); } catch (Sneeze s) { System.out.println(„Caught Sneeze“); } catch (Annoyance a) { System.out.println(„Caught Annoyance“); } } } 122 Exceptions Die Sneeze Exception wird natürlich von der ersten CatchKlausel gefangen. Wenn die erste Catch-Klausel gelöscht wird, so ist der code immer noch lauffähig, da catch (Annoyance) alle AnnoyanceExceptions oder von ihr abgeleiteten Exceptions fängt. Umdrehen der catch-Klauseln zu try { throw new Sneeze(); } catch (Annoyance a) { System.out.println(„Caught Annoyance“); } catch (Sneeze s) { System.out.println(„Caught Sneeze“); } führt zu einem Fehler beim compilieren, da der Compiler, erkennt, daß die Sneeze-Catch-Klausel nie erreicht wird. 123 Interface Schnittstellenvererbung: interface, implements Java kennt keine Mehrfachvererbung im Sinne der Implementierungsvererbung (extends) Durch Vererbung via implements können Schnittstellen vererbt werden Definition von Schnittstellen: interface statt class Implementierung von Schnittstellen: implements statt extends Unterschiede zwischen Vererbung und Interfaces: Eine Klasse kann mehrere Interfaces, aber immer nur eine direkte Oberklasse besitzen Ein Interface hat keine Implementierung, sondern legt nur eine Schnittstelle fest Oberklasse implementiert i.a. das gemeinsame Verhalten von mehreren Unterklassen Interface legt eine gemeinsame Schnittstelle fest, ohne eine Hierarchie aufzubauen 124 Interface Beispiel: // Definition der Schnittstelle interface CDPlayer { public void playNextTitle (); } interface Tuner { public void getNextRadioStation (); } // Ein Server implementiert die Schnittstellen class StereoAnlage extends Elektrogeraet implements CDPlayer, Tuner, etc. { // Die Implementierung wurde versprochen. // Nun wird sie vom Java-Compiler eingefordert! public void playNextTitle () { // Hier kommt die Implementierung hin! } public void getNextRadioStation (){ // Hier kommt die Implementierung hin! } } // Ein Client benutzt die Geraete class Wohnzimmer { ... Irgendeine Methode ... // Neues Geraet kaufen Stereoanlage hifikiste= new StereoAnlage (...); // Das Geraet verspricht einiges.... ..... hifikiste.playNextTitle(); hifikiste.getNextRadioStation(); .... } 125 Interface Beispiel: public interface LautesTier { public void gibtLaut() ; } public class Katze implements LautesTier { public void gibtLaut() { System.out.println("Miau!"); } } public class Hund implements LautesTier { public void gibtLaut() { System.out.println("Wau wau!"); } } public class Katzenmusik { public static void main (String[] args) { LautesTier tier1 = new Katze(); LautesTier tier2 = new Hund(); for (int i=1; i<=10; i++) { tier1.gibtLaut(); tier2.gibtLaut(); } } } 126 Interface Schnittstelle: Vertrag zwischen Auftraggeber (Client) und Auftragnehmer (Server) Implementierung der Funktionalität durch den Auftragnehmer (Server) Anwender (Clients) benötigen kein Wissen über Implementierungen von irgendwelchen Objekten, sondern lediglich die Beschreibung der Schnittstelle Der Anbieter eines Dienstes (Server) implementiert den Dienst, indem die Klasse von der Schnittstelle abgeleitet wird. Danach werden alle Methoden des Dienstes überschrieben Eine Klasse kann im Sinne dieser Theorie mehrere Schnittstellen implementieren 127 Applets • „Minianwendung“ für die Ausführung in einem Web-Browser oder in einem Applet-Viewe • Keine main ( )-Methode • Neues Applet ist Subklasse von Applet • Funktionalität des eigenen Applets durch Überschreiben von Standardmethoden, die bei Bedarf aufgerufen werden: init(), destroy(), start(), stop(), paint() etc. • Sicherheitsbeschränkungen (Kein Zugriff auf das lokale Dateisystem „Sandkastenprinzip“) 128 Applets Erstellen eines Applets: import java.applet.*; import java.awt.*; public class FirstApplet extends Applet { public void paint(Graphics g) { g.drawString("Hello World", 25, 50); } } Ausgabe des Applets: HTML-Datei: HTML> <HEAD> <TITLE>Das Zeichen-Applet</TITLE> </HEAD> <BODY> <P> <APPLET code="FirstApplet.class" width=500 height=300> </APPLET> </BODY> </HTML> 129 Applets Aufruf des Appletviewers: appletviewer FirstApplet.html Darstellung im Appletviewer 130 Applets Darstellung im WWW-Browser Öffnen mit Menüpunkt Open Page des File Menüs im Netscape Browser 131 Applets Erstellen eines weiteren Applets import java.applet.*; import java.awt.*; public class SecondApplet extends Applet { static final String message = "Hello World"; private Font font; public void init() { font = new Font("Helvetica", Font.BOLD, 48); } public void paint(Graphics g) { // The pink oval g.setColor(Color.pink); g.fillOval(10, 10, 330, 100); g.setColor(Color.red); g.drawOval(10,10, 330, 100); g.drawOval(9, 9, 332, 102); g.drawOval(8, 8, 334, 104); g.drawOval(7, 7, 336, 106); // The text g.setColor(Color.black); g.setFont(font); g.drawString(message, 40, 75); } } 132 Applets Die HTML-Datei <HTML> <APPLET code="SecondApplet.class" width=500 height=300> </APPLET> </HTML> Aufruf des Appletviewers: appletviewer SecondApplet.html Darstellung im Appletviewer 133 Applets Darstellung im WWW-Browser Öffnen mit Menüpunkt Open Page des File Menüs im Netscape Browser 134 Applets Weitere Beispiele import java.awt.*; import java.applet.Applet; public class FirstShapes extends Applet { public void paint (Graphics g) { g.drawRect (30, 30, 80, 40); g.drawOval (120, 30, 50, 50); g.setColor (Color.black); g.fillRect (30, 100, 80, 40); g.fillOval (120, 100, 50, 50); g.drawLine (30, 160, 130, 170); g.drawArc (30, 180, 50, 50, 60, 40); g.fillArc (120, 180, 50, 50, 60, 40); } } HTML-Datei <html> <body> <applet code=FirstShapes.class width=300 height=300> </applet> </body> </html> 135 Applets 136 Applets import java.applet.*; import java.awt.*; public class Scribble1 extends Applet { private int lastx, lasty; //Letze Mauskoordinaten Button clear_button; // Clear button Graphics g; // Graphics Objekt zum Zeichnen public void init() { clear_button = new Button("Clear"); this.add(clear_button); g = this.getGraphics(); } public boolean mouseDown(Event e, int x, int y) { lastx = x; lasty = y; return true; } public boolean mouseDrag(Event e, int x, int y) { g.setColor(Color.black); g.drawLine(lastx, lasty, x, y); lastx = x; lasty = y; return true; } public boolean keyDown(Event e, int key) { if ((e.id == Event.KEY_PRESS) && (key == ’c’)) { clear(); return true; } else return false; } public boolean action(Event e, Object arg) { if (e.target == clear_button) { clear(); return true; } else return false; } public void clear() { 137 g.setColor(this.getBackground()); Applets Applet zu Beginn Applet nach dem Zeichnen 138 Events Events • Grafische Anwendungen werden über Events gesteuert. D.h. sie machen nichts, solange der Benutzer nicht die Maus bewegt, einen Button anklickt oder eine Taste drückt. • Unterschiedliche Eventmodelle bei Java 1.0 und Java 1.1. • Viele Web-Browser benutzen noch das alte Eventmodell von Java 1.0 Das Event-Modell von Java 1.0 • Alle Events werden durch die Event-Klasse repräsentiert. (java.awt.Event) Diese Klasse besitzt eine Reihe von Instanzvariablen, die das Event beschrieben. • Eine dieser Variablen (id) gibt zum Beispiel den Typ des Events an. In der Klasse Event ist eine Reihe von Konstanten definiert, die mögliche Werte des id-Feldes darstellen. • Events werden zuerst an die handleEvent()-Methode des ComponentObjektes übergeben, in dem sie aufgetreten sind. (Component ist die Superklasse aller GUI-Komponenten). 139 Events Das Event-Modell von Java 1.0 (Fortsetzung) • Die Standardimplementierung dieser Methode untersucht das id-Feld des Event-Objektes und gibt die am häufigsten vorkommenden Typen an verscheidene typspezifische Methoden weiter: • Die oben aufgeführten Methoden sind in der Component Klasse definiert. Um die entsprechenden Events nach eigener Wahl behandeln zu können, müssen diese Methoden durch eigene Methoden überschieben werden. (Unter Umständen muß auch handleEvent() überschrieben werden.) • Die Methode handleEvent() und alle typspezifischen Methoden liefern boolean-Werte zurück. Gib eine Behandlungsmethode false zurück, dann bedeutet das, daß das Event nicht verarbeitet wurde. Diese unverarbeitete Event wird in der Hierarchie nach oben weitergegeben und kann dort behandelt werden. Liefert die Methode true zurück, ist dies ein SIgnal, daß das Event verarbeitet wurde. • Die Verwendung des alten Java 1.0 Event-Modells erzeugt bei neueren Java-Versionen eine „deprecation warning“. 140 Events import java.applet.*; import java.awt.*; public class Scribble1 extends Applet { private int lastx, lasty; //Letze Mauskoordinaten Button clear_button; // Clear button Graphics g; // Graphics Objekt zum Zeichnen public void init() { clear_button = new Button("Clear"); this.add(clear_button); g = this.getGraphics(); } public boolean mouseDown(Event e, int x, int y) { lastx = x; lasty = y; return true; } public boolean mouseDrag(Event e, int x, int y) { g.setColor(Color.black); g.drawLine(lastx, lasty, x, y); lastx = x; lasty = y; return true; } public boolean keyDown(Event e, int key) { if ((e.id == Event.KEY_PRESS) && (key == ’c’)) { clear(); return true; } else return false; } public boolean action(Event e, Object arg) { if (e.target == clear_button) { clear(); return true; } else return false; } public void clear() { g.setColor(this.getBackground()); g.fillRect(0, 0, bounds().width, bounds().height); } } 141 Events Das Event-Modell von Java 1.1 • Bei diesem Event-Modell werden verschiedene Event-Klassen durch verschiedene Java-Klassen repräsentiert. • Jedes Event ist eine Subklasse von java.util.EventObject. • Das Event-Modell basiert auf dem Konzept des „Event-Listeners“. Ein EventListener ist ein Objekt, das Events abfangen möchte. Ein Objekt, das Events generiert (eine Event-Quelle, „event source“), pflegt eine Liste von Listenern, die über auftretende Events informiert werden wollen, und stellt Methoden bereit, die es den Listenern ermöglichen, sich selbst in diese Liste interessierter Objekte einzutragen bzw. sich wieder aus ihr zu entfernen. • Wird ein Event ausgelöst, benachrichtigt die Event-Quelle alle Listener-Objekte, daß ein Event aufgetreten ist. Eine Event-Quelle benachrichtigt ein Event-Listener- Objekt durch den Aufruf einer Methode und die Übergabe eines Event-Objektes. Damit eine Quelle eine Methode des Listeners aufrufen kann, müssen alle Listener die verlangte Methode implementieren. Das wird dadurch sichergestellt, daß alle Event-Listener eines bestimmten Event-Typs ein entsprechendes Interface implementieren. 142 Events import java.applet.*; import java.awt.*; import java.awt.event.*; public class Scribble2 extends Applet implements MouseListener, MouseMotionListener { private int last_x, last_y; public void init() { this.addMouseListener(this); this.addMouseMotionListener(this); } // Methode des MouseListener interface. public void mousePressed(MouseEvent e) { last_x = e.getX(); last_y = e.getY(); } // Methode des MouseMotionListener interface. public void mouseDragged(MouseEvent e) { Graphics g = this.getGraphics(); int x = e.getX(), y = e.getY(); g.drawLine(last_x, last_y, x, y); last_x = x; last_y = y; } // Die anderen Methoden des MouseListener interface. public void mouseReleased(MouseEvent e) {;} public void mouseClicked(MouseEvent e) {;} public void mouseEntered(MouseEvent e) {;} public void mouseExited(MouseEvent e) {;} // Die anderen Methoden des MouseMotionListener interface. public void mouseMoved(MouseEvent e) {;} } 143 Events Erstellen eines weiteren Applets: import java.applet.*; import java.awt.*; import Polynom; public class MyApplet extends Applet { float skalierung; float x_start = - 3; float x_ende = -x_start; int x_koord_start; int x_koord_end; int y_koord_start; int y_koord_end; int x_koord_offset; int y_koord_offset; Polynom p; Graphics g; public void init() { g = this.getGraphics(); } public void zeichne_graph(Polynom fkt, Color c) { // Erster Funktionswert berechnen und Werte zwischenspeichern int x_koord_old = x_koord_start; int y_koord_old; int x_koord, y_koord; float x; float y; // Transformation von x-Bildkoordinatenpunkt zu realem x Wert x = (x_koord_start-x_koord_offset) / skalierung; y = fkt.berechne(x); //Transformation von realem y Wert in Bildkoordinaten y Wert y_koord_old = (int) (y * skalierung); g.setColor(c); for(x_koord=x_koord_start+1;x_koord<x_koord_end;x_koord++) { x = (x_koord-x_koord_offset) / skalierung; y = fkt.berechne(x); y_koord = - (int) (y * skalierung) + y_koord_offset; g.drawLine(x_koord_old, y_koord_old, x_koord, y_koord); x_koord_old = x_koord; y_koord_old = y_koord; } } 144 Events public void koordinatenkreuz() { g.setColor(Color.pink); g.drawLine(x_koord_start,y_koord_offset,x_koord_end,y_koord_offset); g.drawLine(x_koord_offset, y_koord_start, x_koord_offset, y_koord_end); } public void zeichne_graph(Polynom fkt) { zeichne_graph(fkt, Color.black); } public void paint(Graphics g) { // Ermittlung der Zeichenfläche und Abbildung der Koordinaten int width = this.getWidth(); int height = this.getHeight(); x_koord_offset = width/2; y_koord_offset = height/2; x_koord_start = 0; x_koord_end = width - x_koord_start; y_koord_start = 0; y_koord_end = height - y_koord_start; skalierung = width/(x_ende - x_start); // Zeichne Koordinatenkreuz koordinatenkreuz(); // Erzeugung eines Polynoms 3. Grades p = new Polynom(1,-2).mult(new Polynom(2,-1).mult(new Polynom(1,1))); zeichne_graph(p, Color.green); zeichne_graph(p.ableitung(), Color.blue); zeichne_graph(p.ableitung().ableitung(), Color.red); } } 145 Events 146 Events Beispiel: import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class DigitalClock extends java.applet.Applet { Font theFont = new Font(„TimesRoman“,Font.BOLD,24); Date theDate; public void paint(Graphics g) { g.setFont(theFont); theDate = new Date(); g.drawString(theDate.toString(),10,50); } } 147 Graphische Benutzeroberfläche Graphische Oberfläche • Oberflächen – Applets – fensterbasierte Applikationen • Elemente – Button – Textfeld – Texteditor – Label – Checkbox – Radio Buttons – DropDown List – List Box – Dialog Box – Menus (Java 1.0 nur bei Applikationen • Anordnung – FlowLayout – Border Layout – Grid Layout – Card Layout 148 Graphische Benutzeroberfläche AWT Oberfläche 149 Graphische Benutzeroberfläche Applets • keine main() Methode • Unterliegen Reihe von Restriktionen (kein lokaler Plattenzugriff, Kommunikation nur mit Host von dem es geladen wurde, „untrusted applet“ Dialogbox • Überschreiben der Methoden – – – – – • init() start() stop() paint(Graphics g) destroy() Ereignisgesteuert (event based) 150 Graphische Benutzeroberfläche Applikationen • Fensterbasierte Anwendungen benutzen zur Darstellung Objekte der Klasse Frame bzw. leiten Unterklassen davon ab. • Ein Frame Objekt besitzt Titelzeile und Rand • Frames können ein Menü besitzen (siehe Seite 13) • Konstruktor: – – • Frame() Frame (String title) Methoden (Auswahl):• String getTitle() – – – – – – – – – – void show() void toFront() void toBack() void setMenuBar(MenuBar mb) void remove(MenuComponent) Frame[] getFrames() void setIconImage(Image img) void setResizable(boolean resizable) void setLayout(LayoutManager mgr) LayoutManager getLayout() 151 Graphische Benutzeroberfläche Button • Konstruktoren: – – • Methoden (Auswahl): – – • Button() Button(text) getLabel() setLabel(String str) Beispiel (Java 1.0): public void init() { txt = new TextField(10); add(txt); click = new Button("Anzeigen"); add(click); } public boolean action(Event e, Object arg) { if (e.target==click) { showStatus(txt.getText()); } else return super.action(e, arg); return true; } 152 Graphische Benutzeroberfläche Textfeld • Konstruktoren: – – – – • Methoden (Auswahl): – – – – – – • TextField() TextField(String text) TextField(int columns) TextField(String text, int columns void setEchoChar( char c )l void setText(String str) String getString() void selectAll() void setEditable(boolean b) boolean isEditable() Beispiel (Java 1.0): TextField tf1, tf2, tf3, tf4; // a blank text field tf1 = new TextField(int columns); // blank field of 20 columns tf2 = new TextField("", 20); // predefined text displayed tf3 = new TextField("Hello!"); // predefined text in 30 columns tf4 = new TextField("Hello", 30); 153 Graphische Benutzeroberfläche TextEditor • Konstruktoren: – – – – • Konstanten: – – – – • TextArea(int rows, int columns) TextArea(String text) TextArea(String text, int rows, int columns) TextArea(String text, int rows, int columns, int scrollbars) SCROLLBARS_BOTH, SCROLLBARS_HORIZONTAL_ONLY SCROLLBARS_NONE SCROLLBARS_VERTICAL_ONLY Methoden (Auswahl): – – – – – – – appendText(String str) insertText(String str, int pos) replaceText(String str, int start, int end) String getText() void setText() void selectAll() setEditable(boolean b) boolean isEditable() 154 Graphische Benutzeroberfläche Label • Konstruktoren: – – – • Konstanten: – – – • Label() Label(String text) Label(String text, int alignment) CENTER LEFT RIGHT Methoden (Auswahl): – – String getText() void setText(String str) 155 Graphische Benutzeroberfläche Chechbox • Konstruktoren (Auswahl): – – – – • Checkbox() Checkbox(String label) Checkbox(String label, boolean state) Checkbox(String label, boolean state, CheckboxGroup) // siehe RadioButton Methoden (Auswahl): – – – boolean getState() boolean setState(boolean b) setLabel(String str) Radiobuttons • Konstruktor: – • CheckboxGroup() Methoden (Auswahl): – – Checkbox getCurrent() boolean setCurrent() 156 Graphische Benutzeroberfläche Auswahlbox • Konstruktor: – • Methoden (Auswahl): – – – – – – – – – • Choice() void add(String item) int countItems() int getSelectedIndex() String getSelectedItem() void insert(String item) void remove(int position) void removeAll() void select(int pos) void select(String str) Beispiel: Choice choice = new Choice(); choice.add("red"); choice.add("green"); choice.add("blue"); 157 Graphische Benutzeroberfläche List • Konstruktor: – – – • Methoden (Auswahl): – – – – – – – – – – • List() List(int rows) List(int rows, boolean multipleSelect) void add(String item) int countItems() void delItem(int index) void delItems(int start, int stop) void deselect(int index) String getItem(int index) int getItemCount() String[] getItems() String getSelectedItem() String[] getSelectedItems() Beispiel: List list = new List(4, true); list.addItem("Java"); list.addItem("C"); list.addItem("C++"); list.addItem("Smalltalk"); list.addItem("Lisp"); list.addItem("Modula-3"); list.addItem("Forth"); 158 Graphische Benutzeroberfläche Dialogbox • Konstruktor (Auswahl): – – – • Dialog(Frame owner) Dialog(Frame owner, boolean modal) Dialog(Frame owner, String title) Methoden (Auswahl): – – – – setTitle(String title) void show() void hide() void setModal(boolean b) 159 Graphische Benutzeroberfläche Menuleisten • Aussehen: • Komponenten: – – – – Frame MenuItem Menu MenuItem 160 Graphische Benutzeroberfläche Menüleisten (Java 1.0) import java.awt.*; public class MenuDemo extends Frame { MenuItem copy, paste, insert, neu, quit, info; MenuDemo (String title){ super(title); MenuBar menubar = new MenuBar(); this.setMenuBar(menubar); Menu file = new Menu("Datei"); Menu edit = new Menu("Bearbeiten"); Menu help = new Menu("Hilfe"); menubar.add(file); menubar.add(edit); menubar.add(help); menubar.setHelpMenu(help); neu = new MenuItem("neu"); file.add(neu); quit = new MenuItem("beenden"); file.add(quit); copy = new MenuItem("Kopieren"); edit.add(copy); paste = new MenuItem("Ausschneiden"); edit.add(paste); insert = new MenuItem("Einfügen"); edit.add(insert); info = new MenuItem("Info"); help.add(info); this.setSize(400, 400); this.show(); } 161 Graphische Benutzeroberfläche Menüleisten (Java 1.0) public boolean action(Event e, Object arg) { if (e.target instanceof MenuItem) { if (e.target==copy) { System.out.println("Kopieren ..."); } else if (e.target==paste) { System.out.println("Ausschneiden ..."); } else if (e.target==insert) { System.out.println("Einfügen ..."); } else if (e.target==quit) { System.out.println("Beenden ..."); System.exit(0); } else System.out.println("sonstwas ..."); return true; } return super.action(e, arg); } public static void main(String[] args) { new MenuDemo("Beispielmenu"); } } 162 Graphische Benutzeroberfläche Menüleisten (Java 1.1) import java.awt.*; import java.awt.event.*; public class MenuDemo extends Frame implements ActionListener { MenuItem copy, paste, insert, neu, quit, info; MenuDemo (String title){ super(title); MenuBar menubar = new MenuBar(); this.setMenuBar(menubar); // Create three pulldown menus for the menubar Menu file = new Menu(„Datei“); Menu edit = new Menu(„Bearbeiten“); Menu help = new Menu(„Hilfe“); menubar.add(file); menubar.add(edit); menubar.add(help); menubar.setHelpMenu(help); neu = new MenuItem(„neu“); file.add(neu); quit = new MenuItem(„beenden“); file.add(quit); copy = new MenuItem(„Kopieren“); edit.add(copy); paste = new MenuItem(„Ausschneiden“); edit.add(paste); 163 Graphische Benutzeroberfläche Menüleisten (Java 1.1) insert = new MenuItem(„Einfügen“); edit.add(insert); info = new MenuItem(„Info“); help.add(info); copy.addActionListener(this); paste.addActionListener(this); insert.addActionListener(this); info.addActionListener(this); neu.addActionListener(this); quit.addActionListener(this); this.setSize(400, 400); this.show(); } public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); System.out.println (str); if (str==“beenden“) { System.exit(0); } } public static void main(String[] args) { new MenuDemo(„Beispielmenu“); } } 164 Graphische Benutzeroberfläche Layoutmanager • • • Verantwortlich für die Plazierung der Komponenten (Buttons, Textfelder, etc.) innerhalb eines Fensters Standard ist FlowLayout weiterer verbreiteter Layoutmanager ist BorderLayout: import java.awt.*; import java.applet.Applet; public class BorderLayoutDemo extends Applet { public void init() { setLayout(new BorderLayout()); add(new Button("North"), BorderLayout.NORTH); add(new Button("South"), BorderLayout.SOUTH); add(new Button("East"), BorderLayout.EAST); add(new Button("West"), BorderLayout.WEST); add(new Button("Center"), BorderLayout.CENTER); } } //<applet code=BorderLayoutDemo.class width=320 // height=200> //</applet> 165 Graphische Benutzeroberfläche Layoutmanager • Ausgabe: • weitere Layoutmanager: – Grid Layout – Card Layout 166 Graphische Benutzeroberfläche import java.awt.*; import java.awt.event.*; public class MenuDemo extends Frame implements ActionListener { MenuItem copy, paste, insert, neu, quit, info; MenuDemo (String title){ super(title); MenuBar menubar = new MenuBar(); this.setMenuBar(menubar); // Create three pulldown menus for the menubar Menu file = new Menu("Datei"); Menu edit = new Menu("Bearbeiten"); Menu help = new Menu("Hilfe"); // Add the menus to the bar, and treat Help menu specially. menubar.add(file); menubar.add(edit); menubar.add(help); menubar.setHelpMenu(help); neu = new MenuItem("neu"); file.add(neu); quit = new MenuItem("beenden"); file.add(quit); copy = new MenuItem("Kopieren"); edit.add(copy); paste = new MenuItem("Ausschneiden"); edit.add(paste); insert = new MenuItem("Einfügen"); edit.add(insert); info = new MenuItem("Info"); help.add(info); copy.addActionListener(this); paste.addActionListener(this); insert.addActionListener(this); info.addActionListener(this); neu.addActionListener(this); quit.addActionListener(this); this.setSize(400, 400); this.show(); } 167 Graphische Benutzeroberfläche public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); System.out.println (str); if (str=="beenden") { System.exit(0); } } public static void main(String[] args) { new MenuDemo("Beispielmenu"); } } 168 Graphische Benutzeroberfläche Beispiel1: import java.awt.*; import java.awt.event.*; public class MenuDemo extends Frame implements ActionListener { MenuItem copy, paste, insert, neu, quit, info; MenuDemo (String title){ super(title); MenuBar menubar = new MenuBar(); this.setMenuBar(menubar); // Create three pulldown menus for the menubar Menu file = new Menu("Datei"); Menu edit = new Menu("Bearbeiten"); Menu help = new Menu("Hilfe"); // Add the menus to the bar, and treat Help menu specially. menubar.add(file); menubar.add(edit); menubar.add(help); menubar.setHelpMenu(help); neu = new MenuItem("neu"); file.add(neu); quit = new MenuItem("beenden"); file.add(quit); copy = new MenuItem("Kopieren"); edit.add(copy); paste = new MenuItem("Ausschneiden"); edit.add(paste); insert = new MenuItem("Einfügen"); edit.add(insert); public static void main(String[] args) { new MenuDemo("Beispielmenu"); } } 169 Graphische Benutzeroberfläche info = new MenuItem("Info"); help.add(info); copy.addActionListener(this); paste.addActionListener(this); insert.addActionListener(this); info.addActionListener(this); neu.addActionListener(this); quit.addActionListener(this); this.setSize(400, 400); this.show(); } public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); System.out.println (str); if (str=="beenden") { System.exit(0); } } 170 Graphische Benutzeroberfläche Beispiel 2: import java.awt.*; import java.awt.event.*; public class DrawFkt1 extends Frame implements ActionListener { MenuItem parabel, sinus, gerade, neu, quit; float skalierung; float x_start = - 4; float x_ende = -x_start; int x_koord_start; int x_koord_end; int y_koord_start; int y_koord_end; int x_koord_offset; //Verschiebung des Ursprungs in x-Richtung int y_koord_offset; //Verschiebung des Ursprungs in y-Richtung Graphics g; int auswahl; final int SINUS=0; final int PARABEL=1; final int GERADE=2; DrawFkt1 (String title){ super(title); genMenu(); this.setSize(400, 400); this.show(); } 171 Graphische Benutzeroberfläche private void genMenu() { MenuBar menubar = new MenuBar(); this.setMenuBar(menubar); // Create three pulldown menus for the menubar Menu file = new Menu("Datei"); Menu edit = new Menu("Auswählen"); // Add the menus to the bar, and treat Help menu specially. menubar.add(file); menubar.add(edit); neu = new MenuItem("neu"); file.add(neu); quit = new MenuItem("beenden"); file.add(quit); parabel = new MenuItem("Parabel"); edit.add(parabel); sinus = new MenuItem("Sinus"); edit.add(sinus); gerade = new MenuItem("Gerade"); edit.add(gerade); parabel.addActionListener(this); sinus.addActionListener(this); gerade.addActionListener(this); neu.addActionListener(this); quit.addActionListener(this); } 172 Graphische Benutzeroberfläche public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); g = this.getGraphics(); if (str=="beenden") { System.exit(0); } else if (str=="Sinus") { auswahl = SINUS; zeichne_graph(Color.green,g); } else if (str=="Parabel") { auswahl = PARABEL; zeichne_graph(Color.blue,g); } else if (str=="Gerade") { auswahl = GERADE; zeichne_graph(Color.red,g); } else { koordinatenkreuz(g); } } public void koordinatenkreuz(Graphics g) { g.setColor(this.getBackground()); g.fillRect(0, 0, this.getWidth(), this.getHeight()); g.setColor(Color.pink); g.drawLine(x_koord_start, y_koord_offset, x_koord_end, y_koord_offset); g.drawLine(x_koord_offset, y_koord_start, x_koord_offset, y_koord_end); } 173 Graphische Benutzeroberfläche public void zeichne_graph(Color c, Graphics g) { // Allererster Funktionswert berechnen und Wertepaar zwischenspeichern // int x_koord_old = x_koord_start; int y_koord_old; int y_koord; float x; float y; // Transformation von x-Bildkoordinatenpunkt zu realem x Wert x = (x_koord_start-x_koord_offset) / skalierung; y = (float) berechne(x); //berechnen des Fkt-Wertes // Transformation von realem y Wert in Bildkoordianten y Wert y_koord_old = (int) (y * skalierung); g.setColor(c); for (int x_koord = x_koord_start + 1; x_koord < x_koord_end; x_koord++) { x = (x_koord-x_koord_offset) / skalierung; y = (float) berechne(x); //berechnen des Fkt-Wertes y_koord = - (int) (y * skalierung) + y_koord_offset; g.drawLine(x_koord_old, y_koord_old,x_koord, y_koord); x_koord_old = x_koord; y_koord_old = y_koord; } } 174 Graphische Benutzeroberfläche public void paint(Graphics g) { // Ermittlung der Zeichenfläche und Abbildung der Koordinaten // g = this.getGraphics(); int width = this.getWidth(); int height = this.getHeight(); System.out.println(0 +"/"+0+" "+width+","+height); x_koord_offset = width/2; x_koord_start = 0; x_koord_end = width; y_koord_start = 50; y_koord_offset = (height+y_koord_start)/2; y_koord_end = height; skalierung = width/(x_ende - x_start); System.out.println("Skalierung: " + skalierung); System.out.println("Zeicheninterval: [" + x_start+","+x_ende+"]"); System.out.println("Koordinatenbereich: [" + x_koord_start+","+x_koord_end+"]"); System.out.println("Koordinatenbereich: [" + y_koord_start+","+y_koord_end+"]"); // Zeichne Koordinatenkreuz koordinatenkreuz(g); } double berechne (double x) { if (auswahl == SINUS) return Math.sin(x); else if (auswahl == PARABEL) return x*x; else return x; } public static void main(String[] args) { DrawFkt1 drawFkt1 = new DrawFkt1("Beispielmenu"); } } 175 Graphische Benutzeroberfläche Beispiel 4: import java.awt.*; import java.awt.event.*; public class TextBox extends Frame implements ActionListener{ TextField lowerBound; Label lowerBoundLabel; Button oklB; int low; final int defaultlow = -4; TextBox (String title){ super(title); setLayout(new FlowLayout(FlowLayout.LEFT, 10,10)); lowerBound = new TextField(String.valueOf(defaultlow),6); lowerBoundLabel = new Label ("Untere Intervallgrenze: "); oklB = new Button("übernehmen"); add(lowerBoundLabel); add(lowerBound); add(oklB); oklB.addActionListener(this); this.setSize(400, 400); this.show(); } public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); System.out.println (str); if (str=="übernehmen") { String tmp = lowerBound.getText(); try { low = Integer.parseInt(tmp); System.out.println("neue Grenze: "+low); } catch (NumberFormatException ne) { lowerBound.setText(String.valueOf(defaultlow)); } } } public static void main(String[] args) { new TextBox("Beispielmenu"); } 176 Graphische Benutzeroberfläche import java.awt.*; import java.awt.event.*; public class TextBox1 extends Frame implements TextListener{ TextField lowerBound; Label lowerBoundLabel; int low; final int defaultlow = -4; TextBox1 (String title){ super(title); setLayout(new FlowLayout(FlowLayout.LEFT, 10,10)); lowerBound = new TextField(String.valueOf(defaultlow),6); lowerBoundLabel = new Label ("Untere Intervallgrenze: "); add(lowerBoundLabel); add(lowerBound); lowerBound.addTextListener(this); this.setSize(400, 400); this.show(); } public void textValueChanged(TextEvent e) { String tmp = lowerBound.getText(); try { low = Integer.parseInt(tmp); System.out.println("neue Grenze: "+low); } catch (NumberFormatException ne) { lowerBound.setText(String.valueOf(defaultlow)); } } public static void main(String[] args) { new TextBox1("Beispielmenu"); } } 177 Graphische Benutzeroberfläche Beispiel 3: import java.awt.*; import java.awt.event.*; public class TextBox2 extends Frame implements ActionListener{ TextField lowerBound; Label lowerBoundLabel; Button oklB; int low; final int defaultlow = -4; TextField upperBound; Label upperBoundLabel; Button okuB; int upper; final int default_upper = 4; TextBox2 (String title){ super(title); setLayout(new FlowLayout(FlowLayout.LEFT, 10,10)); lowerBound = new TextField(String.valueOf(defaultlow),6); lowerBoundLabel = new Label ("Untere Intervallgrenze: "); oklB = new Button("übernehmen"); oklB.setActionCommand("lowOK"); add(lowerBoundLabel); add(lowerBound); add(oklB); oklB.addActionListener(this); upperBound = new TextField(String.valueOf(default_upper),6); upperBoundLabel = new Label ("Obere Intervallgrenze: "); okuB = new Button("übernehmen"); okuB.setActionCommand("upperOK"); add(upperBoundLabel); add(upperBound); add(okuB); okuB.addActionListener(this); this.setSize(400, 400); this.show(); 178 } Graphische Benutzeroberfläche public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); System.out.println (str); if (str=="lowOK") { String tmp = lowerBound.getText(); try { low = Integer.parseInt(tmp); System.out.println("neue Grenze: "+low); } catch (NumberFormatException ne) { lowerBound.setText(String.valueOf(defaultlow)); } } else if (str=="upperOK") { String tmp = upperBound.getText(); try { upper = Integer.parseInt(tmp); System.out.println("neue Grenze: "+upper); } catch (NumberFormatException ne) { lowerBound.setText(String.valueOf(default_upper)); } } if (upper < low) { upper = low; lowerBound.setText(String.valueOf(upper)); upperBound.setText(String.valueOf(upper)); } } public static void main(String[] args) { new TextBox2("Beispielmenu"); } } 179 Graphische Benutzeroberfläche Ergebnis von DrawFkt1 180 Graphische Benutzeroberfläche Ergebnis von Textbox Ergebnis von TextBox1 Ergebnis von TextBox2 181 Streams Das Input-Output-System von Java • Java hat zwei Basisklassen für Input und Output: InputStream und OutputStream • Diese Klassen unterstützen das Lesen und Schreiben von Bytes. • Durch import java.io.* werden diese Klassen eingebunden. • InputStream hat eine Basismethode read() für das Lesen eines einzelnen oder eines Arrays von Bytes. • OutputStream hat eine Basismethode write() für das Schreiben eines einzelnen oder eines Arrays von Bytes. 182 Streams Typen von InputStream Input kann aus verschiedenen Quellen kommen. Solche Quellen können sein: • Array von Bytes • Zeichenkette • Datei • Pipe • Sequenz von anderen Streams, die zu einem einzelnen Stream zusammengefaßt werden • Andere Quelle, wie z.B. Internet-Verbindungen Für diese verschiedenen Quellen gibt es Unterklassen von InputStream, die für diese Quellen erstellt wurden. 183 Streams Typen von OutputStream Output kann in verschiedene Senken fließen. Solche Senken können sein: • Array von Bytes • Datei • Pipe • Andere Senken, wie z.B. Internet-Verbindungen Für diese verschiedenen Senken gibt es Unterklassen von OutputStream, die für diese Senken erstellt wurden. 184 Streams Reader und Writer Die Klassen InputStream und OutputStream sind die Basisklassen für das Lesen und Schreiben von Byte-Streams. Die Klassen Reader und Writer sind zu InputStream und OutputStream identisch, allerdings Lesen und Schreiben diese beiden Klassen Zeichen. Ebenso sind alle Unterklassen jeweils identisch. Beispiel: Anlegen eines ByteArrayInputStreams import java.io.*; class IOdemo { public static void main (String args[]) throws IOException{ byte buffer[] = new byte[80]; int test; for (int i=0;i<buffer.length;i++) buffer[i] = (byte) (i+1); // Fuellen von buffer InputStream s = new ByteArrayInputStream(buffer); //Testweise Lesen der ersten 10 Bytes for (int i = 0; i < 10 ; i++) { test = s.read(); System.out.println("Gelesen: " + test); } } } 185 Streams Andere Art des Exception-Handlings import java.io.*; class IOdemo { public static void main (String args[]) { byte buffer[] = new byte[80]; int test; for (int i=0;i<buffer.length;i++) buffer[i] = (byte) (i+1); // Fuellen von buffer InputStream s = new ByteArrayInputStream(buffer); //Testweise Lesen der ersten 10 Bytes for (int i = 0; i < 10 ; i++) { try { test = s.read(); System.out.println("Gelesen: " + test); } catch (IOException e) { System.out.println("IO Fehler"); } } } } 186 Streams Die Methoden von InputStream int available() Returns the number of bytes that can be read (or skipped over) from this input stream without blokking by the next caller of a method for this input stream. void close() Closes this input stream and releases any system resources associated with the stream. void mark(int readlimit) Marks the current position in this input stream. boolean markSupported() Tests if this input stream supports the mark and reset methods. int read() Reads the next byte of data from the input stream. int read(byte[] b) Reads some number of bytes from the input stream and stores them into the buffer array b. int read(byte[] b, int off, int len) Reads up to len bytes of data from the input stream into an array of bytes. void reset() Repositions this stream to the position at the time the mark method was last called on this input stream. long skip(long n) Skips over and discards n bytes of data from this input stream. 187 Streams Beispiel: Lesen eines Buffers und Schreiben in einen Anderen import java.io.*; class IOdemo1 { public static void main (String args[]) { byte ibuffer[] = new byte[10]; byte obuffer[] = new byte[10]; for (int i=0;i<ibuffer.length;i++) ibuffer[i] = (byte) (i+1); // Fuellen von buffer InputStream s = new ByteArrayInputStream(ibuffer); //Lesen von ibuffer und Schreiben in obuffer try { s.read(obuffer); } catch (IOException e) { System.out.println("IO Fehler"); } //Test durch Ausgabe von obuffer for (int i=0;i<obuffer.length;i++) System.out.println("obuffer["+i+"] = "+ obuffer[i]); } } 188 Streams Die Methoden von OutputStream void close() Closes this output stream and releases any system resources associated with this stream. void flush() Flushes this output stream and forces any buffered output bytes to be written out. void write(byte[] b) Writes b.length bytes from the specified byte array to this output stream. void write(byte[] b, int off, int len) Writes len bytes from the specified byte array starting at offset off to this output stream. void write(int b) Writes the specified byte to this output stream. 189 Streams Beispiel: Lesen aus einem File import java.io.*; class FileDemo { public static void main (String args[]) throws IOException{ int in=0; FileInputStream s = new FileInputStream("tmp1"); in = s.read(); System.out.println("Test = "+ in); } } Beispiel: Schreiben und Lesen eines Files import java.io.*; class FileDemoIO { public static void main (String args[]) throws IOException{ int i=0; FileOutputStream out = new FileOutputStream("tmp2"); out.write(3); FileInputStream in = new FileInputStream("tmp2"); i = in.read(); System.out.println("Test = "+ i); } } 190 Streams Die Klasse File Zum Bearbeiten von Files gibt es die Klasse File. Einige Konstruktoren der Klasse sind: File(File parent, String child) Creates a new File instance from a parent abstract pathname and a child pathname string. File(String pathname) Creates a new File instance by converting the given pathname string into an abstract pathname. File(String parent, String child) Creates a new File instance from a parent pathname string and a child pathname string. Einige Methoden dieser Klasse sind z.B.: boolean canRead() Tests whether the application can read the file denoted by this abstract pathname. boolean canWrite() Tests whether the application can modify to the file denoted by this abstract pathname. int compareTo(File pathname) Compares two abstract pathnames lexicographically. int compareTo(Object o) Compares this abstract pathname to another object. boolean createNewFile() Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist. boolean delete() Deletes the file or directory denoted by this abstract pathname. 191 Streams boolean equals(Object obj) Tests this abstract pathname for equality with the given object. boolean exists() Tests whether the file denoted by this abstract pathname exists. File getAbsoluteFile() Returns the absolute form of this abstract pathname. String getAbsolutePath() Returns the absolute pathname string of this abstract pathname. String getName() Returns the name of the file or directory denoted by this abstract pathname. String getParent() Returns the pathname string of this abstract pathname’s parent, or null if this pathname does not name a parent directory. File getParentFile() Returns the abstract pathname of this abstract pathname’s parent, or null if this pathname does not name a parent directory. String getPath() Converts this abstract pathname into a pathname string. boolean isAbsolute() Tests whether this abstract pathname is absolute. boolean isDirectory() Tests whether the file denoted by this abstract pathname is a directory. boolean isFile() Tests whether the file denoted by this abstract pathname is a normal file. 192 Streams boolean isHidden() Tests whether the file named by this abstract pathname is a hidden file. long lastModified() Returns the time that the file denoted by this abstract pathname was last modified. long length() Returns the length of the file denoted by this abstract pathname. String[] list() Returns an array of strings naming the files and directories in the directory denoted by this abstract pathname. String[] list(FilenameFilter filter) Returns an array of strings naming the files and directoriesin the directory denoted by this abstract pathname that satisfy the specified filter. boolean mkdir() Creates the directory named by this abstract pathname. boolean mkdirs() Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories. boolean renameTo(File dest) Renames the file denoted by this abstract pathname. boolean setLastModified(long time) Sets the last-modified time of the file or directory named by this abstract pathname. boolean setReadOnly() Marks the file or directory named by this abstract pathname so that only read operations are allowed. String toString() Returns the pathname string of this abstract pathname. URL toURL() Converts this abstract pathname into a file: URL. 193 Streams Beispiel: Lesen aus einem File import java.io.*; class FileDemo2 { public static void main (String args[]) throws IOException{ File test = new File("tmp1"); byte ibuffer[] = new byte[5]; test.createNewFile(); FileInputStream s = new FileInputStream(test); try { s.read(ibuffer); } catch (IOException e) { System.out.println("IO Fehler"); } //Test durch Ausgabe for (int i=0;i<ibuffer.length;i++) System.out.println("ibuffer["+i+"] = "+ ibuffer[i]); } } 194 Streams Beispiel: Lesen und Schreiben eines Files import java.io.*; class FileDemo3 { public static void main (String args[]) throws IOException{ File test = new File("tmp1"); int i; test.createNewFile(); FileOutputStream out = new FileOutputStream (test); for (i = 1; i <20; i++) out.write(i); FileInputStream in = new FileInputStream(test); do { i = in.read(); System.out.println("Ergebnis"+ i); } while (i!= -1); } } 195 Threads Einfache Animationen und Threads Eine Animation umfaßt in Java zwei Schritte: • • Erstens Aufbau und Ausgabe eines Animationsrahmens und zweitens entsprechend häufige Wiederholung der Zeichnung, um den Eindruck von Bewegung zu vermitteln. Zeichnen und Nachzeichnen: Die paint()-Methode wird von Java immer aufgerufen, wenn ein Applet gezeichnetwerden muß - beim erstmaligen Zeichnen des Applets, wenn das Applet-Fenster verschoben oder es durch ein anderes Fenster überlagert wird. Mab kann Java aber auch auffordern, ein Applet zu einem bestimmten Zeitpunkt nachzuzeichnen. Um die Darstellung am Bildschirm zu ändern, wird ein Bild erstellt – ein sogenannter »Rahmen« - der gezeichnet werden soll, dann wird Java aufgefordert, diesen Rahmen zu zeichnen. Wird dies wiederholt und schnell genug getan, so erhält man im Java-Applet eine Animation. Mehr ist dazu nicht nötig. Wo findet all dies statt? Nicht in der paint()-Methode. paint() gibt nur Punkte am Bildschirm aus. Mit anderen Worten, paint() ist nur für den aktiven Rahmen der Animation zuständig. Die wirkliche Arbeit dessen, was paint() wirklich bewirkt, die Änderung des Rahmens für eine Animation, findet irgendwo anders in der Definition des Applets statt. In diesem »irgendwo anders« wird der Rahmen erstellt (setzen von Variablen für paint(), definieren von Farben, Fonts oder andere Objekte, die paint() benötigt), dann wird die repaint()-Methode aufgerufen. repaint() ist der Auslöser, der Java veranlaßt, paint() aufzurufen und den Rahmen zu zeichnen. 196 Threads Threads: Was sie sind und wozu man sie braucht Wenn ein Programm abläuft, beginnt es mit der Ausführung seines Initialisierungscodes, ruft Methoden oder Prozeduren auf und fährt mit der Ausführung und Verarbeitung fort, bis es fertig ist oder das Programm beendet wird. Das Programm nutzt einen einzelnen Thread, wobei der Thread für das Programm ein einzelner Kontrollpunkt ist. Multithreading, wie in Java, ermöglicht die Ausführung mehrerer verschiedener Threads gleichzeitig im gleichen Programm, ohne sich gegenseitig zu beeinträchtigen. Schreiben von Applets mit Threads: Um ein Applet zu schreiben, das Threads nutzt, müssen vier Änderungen durchgeführt werden: • Erweitern der Unterschrift des Applets um die Wörter implements Runnable • Einfügen einer Instanzvariablen, die den Thread des Applets enthält • Ändern der start()-Methode, so daß sie außer dem Starten des Threads nichts macht • Erstellen einer run()-Methode, die den eigentlichen Code enthält, der das Applet startet 197 Threads Beispiel: Ein einfacher Thread class ErsterThread extends Thread { public void run () { for (int i = 0; i < 10; i++) { System.out.println (i + „ „); try { sleep (100); } catch (InterruptedException e) { System.out.println (e); } } System.out.println („Ende Thread „ + toString ()); } } public class ErsterThreadDemo { static public void main (String args[]) { ErsterThread thread = new ErsterThread (); thread.start (); System.out.println („Ende main“); } } Ausgabe: misun3:105>java ErsterThreadDemo Ende main ErsterThread: 0 ErsterThread: 1 ErsterThread: 2 ErsterThread: 3 ErsterThread: 4 ErsterThread: 5 ErsterThread: 6 ErsterThread: 7 ErsterThread: 8 ErsterThread: 9 198 Threads Beispiel: Digitale Uhr import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class DigitalThreads extends java.applet.Applet implements Runnable { Font theFont = new Font(„TimesRoman“,Font.BOLD,24); Date theDate; Thread runner; public void start() { if (runner == null); { runner = new Thread(this); runner.start(); } } public void stop() { if (runner != null) { runner.stop(); runner = null; } } public void run() { while (true) { theDate = new Date(); repaint(); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } public void paint(Graphics g) { g.setFont(theFont); g.drawString(theDate.toString(),10,50); } } 199 Threads Beispiel: Mehrere Threads class ErsterThread extends Thread { public void run () { for (int i = 0; i < 10; i++) try { sleep (Math.round (1000.0*Math.random ())); System.out.println („ErsterThread: „ + i); } catch (InterruptedException e) { System.out.println (e); } } } class ZweiterThread implements Runnable { Thread thread; ZweiterThread () { thread = new Thread (this); } public void start () { thread.start (); } public void join () throws InterruptedException { thread.join (); } public void run () { for (int i = 0; i < 10; i++) try { thread.sleep (Math.round (1000.0*Math.random ())); System.out.println („ZweiterThread: „ + i); } catch (InterruptedException e) { System.out.println (e); } } } 200 Threads public class ThreadDemo { static public void main (String args[]) { ErsterThread thread1 = new ErsterThread (); thread1.start (); ZweiterThread thread2 = new ZweiterThread (); thread2.start (); try { thread1.join (); thread2.join (); } catch (InterruptedException e) { System.out.println (e); } } } Ausgabe: misun3:106>java ThreadDemo ErsterThread: 0 ZweiterThread: 0 ZweiterThread: 1 ZweiterThread: 2 ErsterThread: 1 ZweiterThread: 3 ErsterThread: 2 ZweiterThread: 4 ZweiterThread: 5 ErsterThread: 3 ErsterThread: 4 ErsterThread: 5 ZweiterThread: 6 ZweiterThread: 7 ZweiterThread: 8 ZweiterThread: 9 ErsterThread: 6 ErsterThread: 7 ErsterThread: 8 ErsterThread: 9 201 Threads Beispiel: class ErsterThread extends Thread { public void run () { for (int i = 0; i < 10; i++) { System.out.println (i + " "); try { sleep (100); } catch (InterruptedException e) { System.out.println (e); } } System.out.println ("Ende Thread " + toString ()); } } public class ErsterThreadDemo { static public void main (String args[]) { ErsterThread thread = new ErsterThread (); thread.start (); System.out.println ("Ende main"); } } 202 Threads Beispiel: import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class DigitalThreads extends java.applet.Applet implements Runnable { Font theFont = new Font("TimesRoman",Font.BOLD,24); Date theDate; Thread runner; public void start() { if (runner == null); { runner = new Thread(this); runner.start(); } } public void stop() { if (runner != null) { runner.stop(); runner = null; } } public void run() { while (true) { theDate = new Date(); repaint(); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } public void paint(Graphics g) { g.setFont(theFont); g.drawString(theDate.toString(),10,50); } } 203 Threads class ErsterThread extends Thread { public void run () { for (int i = 0; i < 10; i++) try { sleep (Math.round (1000.0*Math.random ())); System.out.println ("ErsterThread: " + i); } catch (InterruptedException e) { System.out.println (e); } } } class ZweiterThread implements Runnable { Thread thread; ZweiterThread () { thread = new Thread (this); } public void start () { thread.start (); } public void join () throws InterruptedException { thread.join (); } public void run () { for (int i = 0; i < 10; i++) try { thread.sleep (Math.round (1000.0*Math.random ())); System.out.println ("ZweiterThread: " + i); } catch (InterruptedException e) { System.out.println (e); } } } 204 Threads public class ThreadDemo { static public void main (String args[]) { ErsterThread thread1 = new ErsterThread (); thread1.start (); ZweiterThread thread2 = new ZweiterThread (); thread2.start (); try { thread1.join (); thread2.join (); } catch (InterruptedException e) { System.out.println (e); } } } 205 Ergänzungen Abstract Windowing Toolkit (AWT) Das Abstract Windowing Toolkit (AWT) ist ein Package, das Klassen für die Zusammenstellung und Verwendung von graphischen Benutzungsoberflächen (GUI) enthält. Solche GUIs bestehen aus Fenstern, Menüs, Eingabefeldern, Buttons und dergleichen, und die Steuerung durch den Benutzer erfolgt meistens mit Tastatur (Keyboard) und Maus oder mit ähnlichen Hardware-Komponenten wie z.B. Trackballs, Touchscreen oder Spracheingabe. Das Wort abstrakt (abstract) im Namen AWT deutet darauf hin, dass in diesen Klassen nur die plattformunabhängigen wesentlichen Eigenschaften der Komponenten definiert sind und für die konkrete Darstellung dann die am jeweiligen Rechner vorhandenen Systemkomponenten ("Peers") mit den auf diesem Rechner üblichen Layouts, Aussehen und Funktionalitäten ("look and feel") verwendet werden. Ein im Java-Programm mit AWT definierter Button wird also auf einem PC wie normale Windows- Buttons, auf einem Macintosh wie normale Apple-Buttons und unter Unix wie normale Motif- oder CDE-Buttons aussehen, und das gleiche gilt für Fenster, Scrollbars, Menüs etc. Dies hat für den Benutzer den Vorteil, dass er auf seinem Computersystem immer dieselben, gewohnten GUI-Komponenten vorfindet, unabhängig von der Applikation. Es hat aber den Nachteil, dass die gleiche Applikation auf verschiedenen Computersystemen dadurch in den Details verschieden aussieht und dass im Fall von Applets keine genaue Anpassung der Größen, Farben, Schriftarten und Graphik-Elemente an die umgebende Web-Page möglich ist. 206 Ergänzungen Deshalb unterstützen neuere Java-Versionen (Swing, JDK 1.2) zusätzlich zu den Peer-Komponenten auch sogenannte "leichte„ (light weight) Komponenten, die komplett in Java geschrieben sind und bei denen die Layout-Details genauer definiert werden können. Damit kann man Applets und Applikationen so gestalten, dass jede Anwendung plattformübergreifend ihr eigenes Look-and-Feel hat. Die Swing-Komponenten sind Teil der sogenannten Java Foundation Classes (JFC). Sie können beim JDK 1.1 zusätzlich installiert werden und sind ab JDK 1.2 Teil des JDK. Sie werden von den meisten Web-Browsern noch nicht unterstützt. Für AWT Version 1.1 müssen die Packages java.awt und java.awt.event importiert werden, für Swing zusätzlich das Package javax.swing. 207 Ergänzungen Swing-Komponenten (JComponent) In Swing (Java Foundation Classes JFC) stehen als Alternative zu den AWT-Komponenten die folgenden Komponenten zur Verfügung. Sie verwenden keine Peers vom Betriebssystem, sondern sind komplett in Java definiert. Man kann das Aussehen und die Funktionalität (look and feel) für diese Komponenten im Java-Programm genau festlegen: entweder, indem man eines der vorgefertigten Designs auswählt (z.B. wie bei Motif oder wie bei Windows) oder, indem man alle Details selbst festlegt und damit ein produktspezifisches Look-and-Feel erzeugt. Swing-Komponenten sollten niemals mit Peer-Komponenten gemischt verwendet werden. Die wichtigsten Swing-Kompontenten sind: • JFrame mit ContentPane, für ein Fenster mit Rahmen (wie Frame) • JPanel, JInternalFrame, JDesktopPane, JLayeredPane, JTabbedPane, JApplet für einen Bereich (wie Panel bzw. Applet) • JComponent als Oberklasse für alle Swing-Komponenten und Container, und für eine Zeichenfläche (wie Canvas und Panel) • JLabel für einen Text oder ein Icon (wie Label) • JButton für einen Knopf mit Text oder Icon (wie Button) • JCheckbox, JRadioButton, JToggleButton für einen Schalter (wie Checkbox) • JList, JComboBox in Verbindung mit einem Vector oder einem ListModel bzw. ComboBoxModel und ListCellRenderer für Auswahllisten (wie Choice bzw. List) • JTextField, JPasswordField, JTextArea in Verbindung mit String oder Document, für Text-Eingaben (wie TextField bzw. TextArea) 208 Ergänzungen • JDialog, JOptionPane für Dialogfenster (wie Dialog) • JFileDialog, JFileChooser für die Auswahl einer Datei (wie FileDialog) • JMenuBar, JMenu, JMenuItem, JCheckboxMenuItem, JPopupMenu, JSeparator für Menüs (wie MenuBar, Menu etc.) • JScrollBar, JScrollPane für Scrollbars (wie ScrollBar bzw. ScrollPane) • ImageIcon für ein kleines Bild • JProgressBar für die graphische Darstellung eines Zahlenwertes • JSlider für die graphische Eingabe eines Zahlenwertes • JColorChooser für die Auswahl einer Farbe • JToolBar für eine Button-Leiste • JToolTip bzw. setToolTipText() für eine Zusatzinformation zu jeder Komponente • JTable in Verbindung mit TableModel und TableCellRenderer für die Anordnung von Komponenten in Tabellenform • JTree in Verbindung mit TreeModel, TreePath, TreeNode und TreeCellRenderer oder TreeCellEditor sowie TreeSelectionModel und TreeSelectionListener für die Darstellung eines hierarchischen Baums von Elementen wie z.B. ein Directory mit Subdirectories und Files • JEditorPane, JTextPane in Verbindung mit einem String oder einem InputStream oder Reader oder einem Document wie PlainDocument, DefaultStyledDocument oder HTMLDocument mit HyperlinkListener, und mit einem EditorKit wie DefaultEditorKit, HTMLEditorKit oder RTFEditorKit, für die formatierte Darstellung von Text. Die HTML-Unterstützung ist dabei nur relativ einfach, für "besseres" HTML gibt es, alleridngs nicht kostenlos, eine HotJava-Bean von der Firma Sun. 209 Ergänzungen Abstrakte Klassen Abstrakte Klassen (abstract class) stellen eine Mischung aus Superklassen und Interfaces dar: ein Teil der Methoden ist in der abstrakten Klasse konkret definiert wie bei Superklassen, und von einem anderen Teil ist nur die Signature der Methoden skizziert, wie bei Interfaces. Die Definition beginnt mit public abstract class SuperClassName und die Vererbung in der Subklasse wie gewohnt mit public class SubClassName extends SuperClassName Die Subklasse muss dann konkrete Implementierungen von allen in der Superklasse nur skizzierten Methoden enthalten und kann die dort konkret definierten Methoden entweder übernehmen (Vererbung) oder überschreiben (override). Innere Klassen (inner class) Ab JDK 1.1. kann man Klassen auch innerhalb von anderen Klassen definieren, sie können dann nur innerhalb dieser Klasse verwendet werden, haben aber (im Gegensatz zu separat definierten Klassen) Zugriff auf alle in der äußeren Klasse definierten Datenfelder und Methoden. 210 Ergänzungen Packages und import Unter einem Package versteht man eine Menge von zusammengehörenden Klassen, ähnlich wie bei einer Programmbibliothek. Package ist im wesentlichen identisch mit Directory: Alle Klassen, die im selben Directory liegen, gehören zu diesem Package. In Java werden Packages einheitlich und plattformunabhängig mit Punkten zwischen den Directory-Namen geschrieben, egal, ob auf der jeweiligen Plattform Schrägstriche / oder Backslashes \ oder sonst etwas als FileSeparator verwendet wird. Wenn man in einer Java-Klasse andere Klassen oder Interfaces ansprechen will, muss man diese im allgemeinen "importieren". Dazu gibt man am Beginn des Source-Files mit import den Namen der Klasse (meist mit ihrem Package-Namen) an, oder man importiert gleich alle Klassen eines Package, indem man einen Stern * angibt: import aaa.bbb.Xxxx ; import aaa.bbb.* ; Im ersten Fall wird die Klasse Xxxx aus dem Package aaa.bbb verfügbar gemacht, im zweiten Fall alle Klassen aus dem Package aaa.bbb. Die Angabe der Packages (Directories) erfolgt immer relativ zu den Directories, die in der Environment-Variablen CLASSPATH angeführt sind. 211 Ergänzungen Wenn der Punkt . für das jeweilige Directory in CLASSPATH enthalten ist, dann braucht man für Klassen, die im selben Directory liegen, kein importStatement anzugeben, sondern alle Klassen, die im selben Directory liegen, stehen automatisch zur Verfügung. Das zur Grundausstattung von Java gehörende Package java.lang und das "eigene" Package (eigenes Directory oder package-Angabe) werden vom Compiler automatisch gefunden und müssen nicht explizit importiert werden, wohl aber alle anderen wie z.B. java.util, java.text, java.awt, java.awt.event etc. 212 Ergänzungen Java-Archive (jar) Ein Java-Archiv enthält Dateien und eventuell auch ganze DirectoryStrukturen (siehe Packages) in demselben komprimierten Format, das auch von PKZIP und Win-Zip verwendet wird. Sie werden mit dem Programm jar (java archiver)verwaltet, der Aufruf erfolgt ähnlich wie beim Unix-Programm tar (tape archiver): Archiv-File erstellen (create): jar cvf xxx.jar *.class Inhalt eines Archiv-Files anzeigen (table of contents): jar tvf xxx.jar einzelen Dateien aus einem Archiv-File herausholen (extract): jar xvf xxx.jar Yyyy.class Der Herausholen bzw. "Auspacken" von Archiv-Files ist meistens gar nicht nötig: Der Java-Compiler und die Java Virtual Machine können die ClassFiles direkt aus dem Archiv-File lesen und laden. Zu diesem Zweck muss der Filename des Archiv-Files im Classpath angegeben sein bzw. bei Applets im ARCHIVE-Paremeter des Applet-Tag im HTML-File. 213 Ergänzungen Java im Web-Server (CGI, Servlets) Web-Server können nicht nur fertige Files liefern sondern auch Programme ausführen. Dazu dient die Schnittstelle Common Gateway Interface (CGI). Die CGI-Programme können, eventuell in Abhängigkeit von BenutzerEingaben, irgendwelche Aktionen ausführen und die Ergebnisse über das Hypertext Transfer Protocol HTTP an den Web-Browser senden. CGI-Programme können im HTML-File oder Applet entweder über ein Hypertext-Link aufgerufen werden (nur Ausgabe an den Client) oder über ein Formular oder GUI (Eingabe vom Client an das CGI-Programm, Ausgabe an den Client). CGI-Programme können in jeder beliebigen Programmier- oder ScriptSprache geschrieben werden, auch in Java. In diesem Fall besteht das CGI-Programm aus einem Shell-Script, in dem die Java Virtual Machine aufgerufen wird, die den Bytecode der Java- Applikation interpretiert, etwa in einer der folgenden Formen: java Classname java Classname Parameter java -Dvariable=wert Classname Dies bedeutet, dass bei jedem Aufruf des CGI-Programms die Java Virtual Machine neu gestartet werden muss, was eventuell zu längeren Wartezeiten führen kann. Diesen Nachteil kann man vermeiden, wenn man einen Web-Server verwendet, der die Java Virtual Machine integriert enthält und JavaProgramme sofort direkt aufrufen kann (z.B. die neueren Versionen von Apache, Netscape Enterprise Server und vielen anderen). 214 Ergänzungen Diese Java-Programme werden als Servlets bezeichnet. Der Name "Servlet" ist analog zu "Applet" gebildet: So wie Applets von einer Java Virtual Machine innerhalb des Web-Browsers ausgeführt werden, so werden Servlets von einer Java Virtual Machine innerhalb des Web-Servers ausgeführt. Dafür gibt es die Packages javax.servlet und javax.servlet.http sowie ein Java Servlet Development Kit JSDK mit einem ServletRunner zum Testen von Servlets, bevor sie im echten Web- Server eingebaut werden. Die wichtigsten Methoden von Servlets sind: Wenn der Web-Server startet und die Servlets initialisiert, wird die init-Methode ausgeführt. Bei jedem Client-Request ("User-Click") wird die service-Methode oder die von dort je nach der Request-Methode aufgerufene Methode doGet, doPost etc. ausgeführt. Diese Methoden haben 2 Parameter: Mit dem Parameter ServletRequest können die vom Client mitgesendeten Informationen abgefragt werden. Mit dem Parameter ServletResponse muss die Antwort an den Client gesendet werden. Mit der Methode getServletInfo kann man das Servlet dokumentieren. Servlets können wie Java-Applikationen auch auf lokale Files, Programme und Systemfunktionen am Web-Server zugreifen. 215 Ergänzungen Internet-Protokoll, Server und Clients Java unterstützt die Kommunikation über das weltweite Internet und über interne Intranets und Extranets mit den Internet- Protokollen TCP und UDP. Dazu muss das Package java.net importiert werden. Grundbegriffe: Die programmtechnischen Mechanismen für Netzverbindungen werden Sockets (vom englischen Wort für Steckdose) genannt. Für die Adressierung werden Hostname und Portnummer verwendet. Der Hostname ist eine weltweit bzw. netzweit eindeutige Bezeichnung des Rechners (Name oder Nummer). Die Portnummer gibt an, welches Programm auf diesem Rechner die über das Netz übertragenen Informationen verarbeiten soll. Portnummern unter 1024 haben eine vordefinierte Bedeutung und können nur mit SupervisorPrivilegien (root unter Unix) verwendet werden. Portnummern über 1024 sind "frei". Für Java- Anwendungen, die von gewöhnlichen Benutzern geschrieben werden, kommen also meist nur Portnummern über 1024 in Frage, und man muss sicherstellen, dass nicht jemand anderer auf demselben Rechner dieselbe Portnummer schon für andere Zwecke verwendet. Server sind die Rechner, die ein bestimmtes Service bieten und damit die Kunden (Clients) "bedienen". Clients ("Kunden") sind die Benutzer, die das Service des Servers in Anspruch nehmen wollen, bzw. die von ihnen dafür benützten Rechner. 216 Ergänzungen Vorgehensweise: Der Server "horcht" (listen) mit Hilfe einer ServerSocket auf eine Portnummer, d.h. er wartet darauf, dass ein Client etwas von ihm will ("einen Request sendet"). In diesem Fall baut er, meist in einem eigenen Thread, eine Verbindung (connection) mit dem Client über eine Socket auf, liest eventuell vom Client kommende Befehle und Dateneingaben und sendet jedenfalls Meldungen und Ergebnisse an den Client. Clients bauen über eine Socket eine Verbindung (connection) zum Server auf, senden eventuell Befehle oder Daten an den Server und lesen jedenfalls alle vom Server kommenden Informationen. 217 Ergänzungen Datenbanken Zu den wichtigsten Anwendungsgebieten von Java zählen UserInterfaces zu Datenbanksystemen. Das Java-Programm kann dabei ein Applet, eine Applikation oder ein Servlet sein und kann am selben Rechner wie die Datenbank laufen oder auch auf einem anderen Rechner und von dort über das Internet oder ein Intranet auf die Datenbank zugreifen. Die "Java Database Connectivity" (JDBC) ist im Sinne der Plattformunabhängigkeit von Java so aufgebaut, dass das Java- Programm von der Hard- und Software des Datenbanksystems unabhängig ist und somit für alle Datenbanksysteme (MS-Access, Oracle etc.) funktioniert. Mit den im JDBC enthaltenen Java-Klassen (Package java.sql) kann man Daten in der Datenbank so bequem speichern und abfragen wie beim Lesen und Schreiben von Dateien oder Sockets. Auf diese Weise kann man die Vorteile von Java, die vor allem bei der Gestaltung von (graphischen und plattformunabhängigen) User-Interfaces liegen, mit der Mächtigkeit von Datenbanksystemen verbinden. 218 Ergänzungen Java Beans Unter Java Beans ("Kaffeebohnen") versteht man kleine Java- Programme (Klassen) mit genau festgelegten Konventionen für die Schnittstellen, die eine Wiederverwendung in mehreren Anwendungen (Applikationen und Applets) ermöglichen, ähnlich wie bei Unterprogramm-Bibliotheken in anderen Programmiersprachen. Dies ist vor allem in Hinblick auf das Software-Engineering von komplexen Programmsystemen interessant. Dafür gibt es ein eigenes Beans Development Kit BDK, das man zusätzlich zum JDK installieren kann, und ein Package java.beans, das ab Version 1.1 im JDK enthalten ist, Beans werden auch von vielen Software-Tools (IDE) unterstützt. Auch die Klassenbibliothek des JDK ist seit Version 1.2 weitgehend nach den BeansKonventionen geschrieben, und manche Softwarefirmen verkaufen spezielle Java-Beans für bestimmte Anwendungen. Es ist empfehlenswert, auch beim Schreiben eigener Java-Programme möglichst die Konventionen von Java-Beans einzuhalten, also z.B. dass jede Klasse einen Default-Konstruktor mit leerer Parameterliste haben soll, dass die Methoden für das Setzen und Abfragen von Datenfeldern Namen der Form setXxxxx und getXxxxx bzw. isXxxxx haben sollen, oder dass alle Klassen so "selbständig" programmiert werden sollen, dass sie unabhäng davon funktionieren, wie andere Klassen programmiert wurden. 219 Ergänzungen Verwendung von Unterprogrammen (native methods, JNI) Man kann innerhalb von Java-Applikationen auch Unterprogramme aufrufen, die in einer anderen Programmiersprache geschrieben sind, insbesondere in den Programmiersprachen C und C++. Solche Unterprogramme werden als "eingeborene" (native) Methoden bezeichnet, das entsprechende Interface als Java Native Interface (JNI). Der Vorteil liegt darin, dass man sämtliche von dieser Programmiersprache unterstützten Funktionen und Unterprogramm-Bibliotheken verwenden kann. Der Nachteil liegt darin, dass die Java-Applikation dann im allgemeinen nicht mehr Plattform- oder auch nur Rechner-unabhängig ist. 220