© 2004-2006, Rainer Schmidberger, ISTE Einführung in die Programmiersprache Java Rainer Schmidberger [email protected] se se © 2004-2006, Rainer Schmidberger, ISTE Teil 1: Übersicht zu Java Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Die Entwicklung 1991 – 1994 Entwicklung der Sprache Oak Anfang 1996: JDK 1.0 Anfang 1997: JDK 1.1 Ende 1998: Java 2 SE v1.2 (alias JDK 1.2) Mitte 2000: Java 2 SE v1.3 (alias JDK 1.3) „Sturm und Drang“-Phase Ende 2001: JDK 1.4 (64 Architektur) Ende 2004: JDK 1.5 („Tiger“, Generische Klassen) Java 2 gibt es in den Varianten Micro Edition (ME): eingebettete Systeme Standard Edition (SE): „normales“ JDK Enterprise Edition (EE): Enterprise JavaBeans, Servlets, … se Folie 3 Download: http://java.sun.com Reference Manual: http://java.sun.com/j2se/1.4/docs/api/index.html Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Online Dokumentation se Folie 4 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Java ist … se einfach objektorientiert plattformunabhängig portabel verteilt robust sicher interpretiert schnell parallel (Threads) dynamisch für Web-Server-Anwendungen geeignet Folie 5 Applikationen Ö selbständige „normale“ Programme Ö werden mit dem Java-Interpreter direkt ausgeführt Ö keine Sicherheitseinschränkungen Applets („Applikatiönchen“) Ö Ö Ö Ö Ö 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Java-Programme unselbständige Programme; spezielle Schnittstelle werden in HTML-Seiten eingebettet werden vom WWW-Browser ausgeführt Sandbox-Prinzip/Sicherheitseinschränkungen Applets laufen in einer kontrollierten Umgebung ab Programmentwicklung, Vorlesungsskript Server-Anwendung se Ö Servlet, generiert serverseitig HTML Ö JSP (Java Server Page) HTML/Java-Mischung zur Erzeugung von HTML Ö Geschäftslogik: EJB (Enterprise Java Beans) Ö Web-Services Folie 6 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Einfaches Beispiel se UML-Darstellung Java-Code Person.java public class Person { private double gehalt; public double getGehalt() { return gehalt; } Person gehalt: double public void setGehalt(int g) { gehalt = g; } gehaltErhoehen() set.... pro Attribut get... public void gehaltErhoehen() { gehalt = gehalt + 100; } } Folie 7 Fest definierter Name der Startmethode public class PersonTest { PersonTest.java public static void main(String[] args) { Person donald = new Person(); donald.setGehalt(1000); 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Testrahmen für die Klasse Person System.out.println("Donald verdient " + donald.getGehalt() + " EUR."); Programmentwicklung, Vorlesungsskript donald.gehaltErhoehen(); se System.out.println("Donald verdient " + donald.getGehalt() + " EUR."); } } Folie 8 Java-Code UML setName(n : String) getName() : String setGehalt(d : double) getGehalt() : double setAlter(a : int) getAlter() : int Programmentwicklung, Vorlesungsskript Programmierer programmierSprache locProStunde setProgrammierSprache(p : String) getProgrammierSprache() : String setLocProStunde(l : int) getLocProStunde() : int se Person.java public class Person { private String name; // ... } Person name : String alter : int gehalt : double 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Vererbung Programmierer.java Manager firmenWagen public class Programmierer extends Person { private String programmierSprache; // ... } setFirmenWagen(f : String) getFirmenWagen() : String Manager.java public class Manager extends Person { private String firmenWagen; // ... } Folie 9 © 2004-2006, Rainer Schmidberger, ISTE Polymorphie UML-Darstellung Person gehaltErhoehen() 08.03.2007 Programmierer gehaltErhoehen() Programmentwicklung, Vorlesungsskript Java-Code Attribut- und Methodennamen müssen nur innerhalb einer Klasse eindeutig sein. Der gleiche Attributname bzw. der gleiche Methodenname kann in anderen Klassen erneut benutzt werden. Dies wird Polymorphismus genannt Überschreiben der Methode gehaltErhoehen() Programmierer-Objekte verhalten sich in diesem Punkt anders als PersonenObjekte. public class Programmierer extends Person { public void gehaltErhoehen() { gehalt = gehalt * 2; } } se Folie 10 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: Polymorphie (1) Java-Code Person donald = new Person(); Programmierer trick = new Programmierer(); donald.setGehalt(1000); trick.setGehalt(1000); System.out.println("Donald verdient " + donald.getGehalt() + " EUR."); System.out.println("Trick verdient " + trick.getGehalt() + " EUR."); donald.gehaltErhoehen(); trick.gehaltErhoehen(); System.out.println("Donald verdient " + donald.getGehalt() + " EUR."); System.out.println("Trick verdient " + trick.getGehalt() + " EUR."); Ausgabe: Donald verdient 1000 EUR. Trick verdient 1000 EUR. Donald verdient 1100 EUR. Trick verdient 2000 EUR. se Folie 11 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: Polymorphie (2) Java-Code public static void main(String args[]) { Person donald = new Person(); Programmierer trick = new Programmierer(); donald.setGehalt(1000); trick.setGehalt(1000); // ... Ausgabe ... testMethode(donald); testMethode(trick); // ... erneute Ausgabe ... // Objekte donald und trick werden an die Methode // testMethode als Parameter übergeben } static void testMethode(Person p) { p.gehaltErhoehen(); // p ist vom Typ Person! } Ausgabe (bleibt unvberändert !!): Donald verdient 1000 EUR. Trick verdient 1000 EUR. Donald verdient 1100 EUR. Trick verdient 2000 EUR. se Folie 12 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Eine Java-Applikation 1. 2. 3. se class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } Compiler erzeugt Bytecode in HelloWorld.class: javac HelloWorld.java HelloWorld.java HelloWorld.class Interpretieren der Datei HelloWorld.class: java HelloWorld (Endung .class weglassen!) Folie 13 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: JBuilder (1) se Folie 14 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: JBuilder (2) Editor mit Syntax-Erkennung Compiler mit Fehlersprung Projekterstellung, Paketbaum GUI-Designer (für Swing und HTML) UML-Darstellung (wie z.B. in XDE, Together) Integration von Versionierung (z.B. ClearCase) Debugger Web-Server Online-Hilfe Suchfunktionen Assistenten Tools wie z.B. Datenbankanbindung u.ä. JBuilder, Visual Café, Together, WSAD se Ö Fazit: wirtschaftliche Entwicklung setzt den Einsatz einer guten Entwicklungsumgebung voraus! Folie 15 JAVA_HOME: enthält das Verzeichnis, in dem die Java-Software abgelegt ist. Beispiel: z.B. /usr/local/java CLASSPATH: enthält die Verzeichnisse, in denen der Interpreter nach .class-Dateien suchen soll. Zip, oder jar Dateien gelten wie Verzeichnisse. Beispiel: set CLASSPATH=%CLASSPATH%;c:\orant817\jdbc\lib\classes12.zip PATH: enthält die Verzeichnisse, in denen das Betriebssystem nach ausführbaren Dateien suchen soll. sollte $JAVA_HOME/bin enthalten Die Variablen sind in der Regel bereits gesetzt. Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Umgebungsvariablen se Folie 16 se © 2004-2006, Rainer Schmidberger, ISTE Teil 2: Java Grundlagen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Kommentare Kommentierter Bereich /* Dies ist ein Kommentar, der über mehrere Zeilen verläuft */ Zeilenkommentar int x = 1; // Anfangswert // ab jetzt folgen Initialisierungen Dokumentationskommentar für javadoc: se /** Liefert alle Einzelverbindungs-Objekte, die ... * ... * geliefert. * @param abfahrtzeit Beginn der Zeitspanne * @return Iterator-Objekt, wobei .... * @see LinienHaltestelle */ Folie 18 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Reservierte Wörter se abstract double int super assert else interface strictfp boolean extends long switch break false native synchronized byte final new this case finally null throw catch float package throws char for private transient class goto protected true const if public try continue implements return void default import short volatile do instanceof static while const und goto werden derzeit (bis einschl. Java 5) nicht genutzt Folie 19 Programmentwicklung, Vorlesungsskript Müssen mit einem Buchstaben beginnen _ zählt als Buchstabe Dann dürfen beliebige weitere Zeichen folgen Achtung: keine Schlüsselwörter verwenden Konventionen: 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Bezeichner se Ö Klassennamen werden groß geschrieben Ö Methodennamen und Attribute werden klein geschrieben Ö Bei Wortzusammensetzungen wird der erste Buchstabe des Folgeworts groß geschrieben (z.B. LayoutManager) Ö Lokale Variablen werden klein geschrieben Ö Konstanten werden durchweg groß geschrieben (z.B. MIN_VAL) Folie 20 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Typenübersicht Referenzdatentypen Alle Klassen aus den Bibliotheken sowie Eigenentwicklungen Standarddatentypen boolean 1 bit byte 8 bit short 16 bit int 32 bit long 64 bit char 16 bit float 32 bit double 64 bit se true/false z.B. 'A', 'b', \u0027 Folie 21 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Klasse Object Object Object() getClass() : Class hashCode() : int equals(arg0 : Object) : boolean clone() : Object toString() : String notify() : void notifyAll() : void wait(arg0 : long) : void wait(arg0 : long, arg1 : int) : void wait() : void finalize() : void Alle Java-Klassen (also selbstgeschriebene und Bibliotheks-Klassen) werden implizit von Object abgeleitet Methoden, die auf Object typisiert sind, sind damit quasi nicht typisiert (Ausnahme BasisDatentypen wie int, ...) Programmentwicklung, Vorlesungsskript Beispiel: Person p = ... Object o = p; se // das ist für alle Referenztypen möglich // ohne, dass die entsprechende Klasse von Object // explizit abgeleitet wäre! Folie 22 Programmentwicklung, Vorlesungsskript se ++, -- Pre-Inkrement, -Dekrement R 16 ++, -- Post-Inkrement, -Dekrement L 15 ~ bitweises Komplement R 14 ! logisches Komplement R 14 +, - Vorzeichen R 14 (typ) Typ-Konvertierung R 13 *, /, % Multiplikation, Division, Modulo L 12 +, - Addition, Subtraktion L 11 <<, >>, >>> Bitweise verschieben L 10 instanceof Typ-Prüfung L 9 <,>, >=, <=, ==, != Vergleiche L 8 & bitweise Und L 7 ^ bitweise Exklusives Oder L 6 | bitweise Oder L 5 && logisches Und L 4 || logisches Oder L 3 ?: Bedingungsoperator R 2 =, *=, /=, %=, +=, -=, <<=, >>=, >>>=, &=, ^=, |= Zuweisung R 1 Operator-Präzedenz 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Operationen R: Abarbeitung von rechts nach links L: Abarbeitung von links nach rechts Folie 23 Inkrement int a = 10, b; b = a++; // -> a = 11, b = 10 b = ++a; // -> a = 12, b = 12 Bedingungsoperator Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Spezielle Operatoren se x = bedingung ? wertFallsBedErfuellt : wertFallsBedNichtErfuellt; Ist gleichbedeutend mit if(bedingung) { x = wertFallsBedErfuellt; } else { x = wertFallsBedNichtErfuellt; } Folie 24 if-Anweisung ... if(a > 20) { // ... } else { // ... } Der else-Teil kann entfallen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Kontrollstrukturen (1) se Folie 25 Schleifen: for, while, do-while Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Kontrollstrukturen (2) se for(int i = 0; i < 10; i++) { // ... } int j = 0; while(j < 10) { j++; // ... } int k = 0; do { k++; // ... } while(k < 10); break: Ablauf abbrechen und nach dem (innersten) Strukturende fortsetzen continue: Ablauf abbrechen und mit nächstem Schleifenwert fortsetzen Folie 26 Fallunterscheidung: switch Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Kontrollstrukturen (3) se switch(wert) { case 1: text = "eins"; break; case 2: text = "zwei"; break; case 3: text = "drei"; break; case 4: text = "vier"; break; default: text = "mehr als vier"; break; } wert muss ganzzahliger Zahlentyp sein wird ein expliziter case nicht gefunden, wird der default-Block eingesprungen Jeder case endet mit einem break, sofern der Fall abgearbeitet ist Folie 27 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Die Klasse String Ab JDK 1.0 wird zur Behandlung von Textoperationen verwendet. Im Paket java.lang enthalten und damit ohne speziellen import verfügbar String-Literal werden in doppelten Anführungszeichen gestellt " Bitte beachten: Zeichenliterale stehen in einfachen Hochkomma Siehe hierzu auch die Klasse StringBuffer // einfaches Beispiel zu Strings String s1 = "Guten"; String s2 = "Morgen"; S3 = s1 + " " + s2; se Folie 28 String s1 = "Kaffee"; String s2 = s1 + "tasse"; // ergibt "affe" char c1 = s2.charAt(6); // ergibt 't' 08.03.2007 String s3 = s2.substring(1, 4); int i1 = s2.indexOf('t'); int i2 = s2.length(); Programmentwicklung, Vorlesungsskript © 2004-2006, Rainer Schmidberger, ISTE Stringoperationen (1) if(s1.equals("Hallo")) { ... // if(s1.compareTo(s2) > 0) { ...// // // // se true oder false ergibt 0, wenn s1 == s2 <0, wenn s1 < s2 >0, wenn s1 > s2 Folie 29 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Stringoperationen (2) String s1 = "Kaffee"; String s2 = "Kaf"; s2 += "fee"; // Achtung: es werden die Objektreferenzen // verglichen! Korrekter Vergleich erfolgt // mit equals() if(s1 == s2) { // ... } if(s1.equals(s2)) { // Vergleich der Inhalte // ... } se Folie 30 Arrays werden durch eckige Klammern [ und ] angegeben Erzeugung mit new unter Angabe der Größe. Diese ist nicht dynamisch erweiterbar! Index beginnt bei 0! Mehrdimensionale Felder entstehen durch Anfügen weiterer Klammern Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Arrays se int a[] = new int[10]; a[4] = 12; System.out.println("a[4] = " + a[4]); System.out.println("Länge von a = " + a.length); int b[][] = new int[3][5]; // 3 Zeilen mit 5 Spalten b[1][4] = 77; Person[] familieDuck = new Person[5]; // Platz für 5 Personen familieDuck[0] = donald; familieDuck[0].updateAlter(); Folie 31 Die main-Methode bekommt ein String-Array mit den Argumenten aus der Kommandozeile übergeben. public class TestArgumente { public static void main(String[] args) { for(int i = 0; i < args.length; i++) { System.out.println(i + ".Argument: " + args[i]); } Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Kommandozeilenparameter } } Ausgabe: se Folie 32 public static void main(String[] args) { Person donald = new Person(); donald.setAlter(45); int a = 45; // hier: donald.getAlter = 45, a = 45 test(donald, a); 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Parameterübergabe // hier: donald.getAlter = 99, a = 45 Programmentwicklung, Vorlesungsskript } static void test(Person donald, int a) { a = 99; donald.setAlter(99); } se Standard-Datentypen wie int, float, double, usw. werden als Wert übergeben (call by value). Es wird in der aufgerufenen Methode eine Kopie erstellt Referenztypen werden als Referenz übergeben (call by reference). Es wird keine Kopie erstellt. Folie 33 Spezielle Klassen aus dem Paket java.io sind zuständig Standardeingabe: InputStream System.in Standardausgabe: PrintStream System.out Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Konsolen Ein-/Ausgabe se import java.io.*; BufferedReader is = new BufferedReader( new InputStreamReader(System.in)); // Zwischenvariable String eingabe; System.out.print("Alter:"); try { eingabe = is.readLine(); int alter = Integer.parseInt(eingabe); } catch(Exception e) { } Folie 34 Wird implizit bei Instanzierung gestartet Kann überladen werden Sonderverhalten bei Vererbung beachten! Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Konstruktor se class Person { // ... public Person() { // Standardkonstruktor } public Person(int a) { // ein überladener Konstruktor alter = a; } // ... } Folie 35 Klassenvariablen werden je Klasse einmal angelegt Klassenmethoden werden über den Klassenbezeichner aufgerufen: Person.getAnzahlPersonen() class Person { // ... static int anzahlPersonen; Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Klassenmethoden und -variablen se public static getAnzahlPersonen() { return anzahlPersonen; } public Person() { anzahlPersonen++; } // ... Attribut anzahlPersonen wird von allen Objekten der Klasse Person geteilt. } Folie 36 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Klassen- und Instanzen Klassenattribut: alle Objekte einer Klasse teilen sich das eine Attribut class Person { // ... private static int anzahlPersonen; // ... } class Person { // ... private int alter; // ... } Klassenmethode: Aufruf erfolgt über Klassenbezeicher: Instanzmethode: Aufruf erfolgt über Objektbezeicher: wert = Person.getAnzahlPersonen(); Programmentwicklung, Vorlesungsskript Instanzattribut: jedes Objekt besitzt physisch ein eigenes Attribut wert = donald.getAlter(); class Person { class Person { // ... // ... public static int getAnzahlPersonen() { public int getAlter() { return anzahlPersonen; return alter; } } // ... // ... } } se Folie 37 „this“ ist ein Zeiger auf das Objekt, in dem die jeweilige Methode abgearbeitet wird Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE this se donald.gehaltErhoehen() class Person { // ... public void gehaltErhoehen() { // ... dieGehaltsStelle.berechneNeuesGehalt (this); // ... } this entspricht in diesem Beispiel dem Objekt, auf das der Bezeichner donald referenziert Folie 38 Zugriff auf Methoden der Vaterklasse Wird oft in überladenen Konstruktoren verwendet Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE super se class Programmierer extends Person { // ... Programmierer(String name) { // überladenen Konstruktor in Person aufrufen super(name); } public void gehaltErhoehen() { // Annahme: der Programmierer erhält die // doppelte Gehaltserhöhung wie die Person super.gehaltErhoehen(); // super wird hier wie ein super.gehaltErhoehen(); // Objektbezeichner verwendet } // ... } Folie 39 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Packages (1) Aufteilung eines Projektes oder Bibliothek zur verbesserten Übersicht. Das JDK selbst besteht aus über 100 Packages Packages können hierarchisch angeordnet werden (entspricht einer Verzeichnisstruktur) Inhaltlich zusammengehörende Klassen werden zu einem Package gruppiert Am Anfang des jeweiligen Quell-Files wird mit package Name die Zugehörigkeit zu einem bestimmten Package bekanntgemacht Klassen ohne package-Zuordnung gehören zu einem "DefaultPackage", was dem aktuellen Verzeichnis entspricht Klassen eines anderen Packages können durch import in der aktuellen Datei bekannt gemacht werden se Ö Einzelne Klassen durch direkte Klassenangabe import java.io.Inputstream; Ö Alle public-Klassen eines Paketes durch * import java.io.*; Folie 40 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Packages: JDK java.lang Provides classes that are fundamental to the design of the Java programming language. java.util Contains the collections framework, legacy collection classes, event model, date and time facilities, internationalization, and miscellaneous utility classes (a string tokenizer, a randomnumber generator, and a bit array). java.text Provides classes and interfaces for handling text, dates, numbers, and messages in a manner independent of natural languages. java.sql Provides the API for accessing and processing data stored in a data source (usually a relational database) using the JavaTM programming language. java.awt Contains all of the classes for creating user interfaces and for painting graphics and images. java.awt.font Provides classes and interface relating to fonts. java.io Provides for system input and output through data streams, serialization and the file system. java.math Provides classes for performing arbitrary-precision integer arithmetic (BigInteger) and arbitrary-precision decimal arithmetic (BigDecimal). javax.swing Provides a set of "lightweight" (all-Java language) components that, to the maximum degree possible, work the same on all platforms. javax.xml.parsers This package defines the generic APIs for processing transformation instructions, and performing a transformation from source to result. ... Unde etwa 100 weitere mehr ... Quelle: Sun Microsystems se Folie 41 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Packages: Beispiel Verzeichnisstruktur: package FachlicheKlassen; import java.text.*; public class Person { // ... } Person.java package FachlicheKlassen; public class Programmierer extends Person { // ... } Programmierer.java Programmentwicklung, Vorlesungsskript package MainPaket; import FachlicheKlassen.*; public class PersonTest { public static void main(String[] args) { Person donald = new Person(); Programmierer trick = new Programmierer(); // ... se PersonTest.java Folie 42 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Packages: Sichtbarkeiten Sichtbarkeiten: ohne Modifier (default oder package), public, protected, private Member zugreifbar für ... public protected "package" private Klasse selbst ja ja ja ja Beliebige Klasse im selben Package ja ja ja nein Kindklasse eines anderen Packages ja ja nein nein Beliebige Klasse eines anderen Packages ja nein nein nein se Folie 43 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Garbage Collector Alle Objekte, auf die keine Referenz mehr besteht, werden automatisch vom Garbage Collector gelöscht Vor dem Löschen eines Objektes wird die finalizeMethode aufgerufen. Hier besteht eine Implementierung in Object. Soll ein Objekt vor der Löschung eine spezielle Funktionalität abarbeiten, muss die finalize-Methode überladen werden. Expliziter Start des Garbage-Collectors mit System.gc(); se Person donald = new Person(); Person p1; p1 = donald; // Objekt mit 1 Referenz p1 = null; donald = null; // nur noch 1 Referenz // Objekt ohne Referenz // jetzt mit 2 Referenzen Folie 44 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Reflektion se Ermitteln der Struktur eines beliebigen Objektes zur Laufzeit Die Klasse Class repräsentiert zur Laufzeit beliebige Java-Klassen. Zugriff auf Methoden und Attribute Verwendung bei sehr generischen Methoden wie z.B. OODatenbank-Anbindung oder Security-Implementierungen Person donald = new Person("Donald", 44); Class personClass = donald.getClass(); Person eineWeiterePerson = (Person)personClass.createInstance(); Field attribute[] = personClass.getDeclaredFields(); for(int i = 0; i < attribute.length; i++) { Field f = attribute[i]; System.out.println(i + ". " + f.getName()); } Field f1 = attribute[0]; System.out.println("f2: " + f1.getName()); f1.set(donald, "Duck"); Folie 45 Typüberprüfung Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE instanceof se Person donald = new Person(); Programmierer trick = new Programmierer(); // ... if(donald instanceof Person) System.out.println("Donald ist eine Person"); if(donald instanceof Programmierer) System.out.println("Donald ist ein Programmierer"); if(trick instanceof Person) System.out.println("Trick ist eine Person"); if(trick instanceof Programmierer) System.out.println("Trick ist ein Programmierer"); Donald ist eine Person Trick ist eine Person Trick ist ein Programmierer Folie 46 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Typ-Wandlung Type cast Explizites formales Wandeln eines Datentyps Person donald = new Person(); Person trick = new Programmierer(); // ... if(trick instanceof Programmierer) { Programmierer p = (Programmierer)trick; p.setProgrammierSprache("Java"); } Achtung: zuvor über instanceof sicherstellen, ob eine Typwandlung überhaupt möglich ist (siehe Beispiel)! se Folie 47 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Exceptions Dienen zur Fehlerbehandlung In Java (und den meisten anderen OO-Sprachen) werden Fehler, die innerhalb einer Methode auftreten, durch eine Exception dem Aufrufer mitgeteilt Tritt in einer Methode ein Fehler auf, wird dieser „geworfen“ (throw). Der Aufrufer der Methode „fängt“ (catch) den Fehler Fehler werden schließlich in einem separaten „catch“-Block behandelt. Hierdurch entsteht eine Trennung von „produktivem“ Programmcode und der Fehlerbehandlung se Folie 48 Viele Methoden des JDK "werfen" im Fehlerfall eine Exception Diese Exceptions können über ein catch "aufgefangen" werden Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Exception (1) se try { Aufgetretener Fehler eingabe = is.readLine(); int alter = Integer.parseInt(eingabe); } catch(Exception e) { // Fehlertext ausgeben System.out.println("Fehler: " + e.getMessage()); // aktuellen Stack auf die System-Konsole ausgeben e.printStackTrace(); } Folie 49 Es können Exceptions verschiedener Klassen über nacheinander folgende catch-Blöcke gefangen werden. Der Typ der geworfenen Exception wird mit dem Typ der zu fangenden Exception verglichen. Bei übereinstimmung wird der jeweilige catch-Block eingesprungen. Der finally-Block wird sowohl im fehlerfreien Fall als auch bei "auffangen" und bearbeiten einer Exception abgearbeitet Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Exception (2) se try { //... Hier können Exceptions geworfen werden ... } catch(IOException e) { System.out.println("Fehler (IO): " + e.getMessage()); } catch(Exception e) { System.out.println("Fehler: " + e.getMessage()); } finally { System.out.println("Programmende"); } Folie 50 Eigene Exceptionklassen können als Kindklasse von Exception implementiert werden Falls eine Methode eine Exception wirft, muss dieses im Interface der Methode angegeben sein Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Exception (3) se class MeineException extends Exception { public MeineException(String s) { super(s); } } class Person // ... public void testMethode() throws MeineException { // ... if(...) throw new MeineException("Hier tut was nicht!"); } } Folie 51 Klassen können auf jeder Ebene eines Blockes deklariert werden und sind innerhalb des Blocks sichtbar. Solche Klassen werden als "Lokale Klassen" bezeichnet. Alle bekannten Merkmale der public-Klassen gelten für lokale Klassen ebenso – mit Ausnahme der Sichtbarkeit. Z.B. kann die Deklaration einer lokalen Klasse innerhalb einer Methode erfolgen. Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Lokale Klassen se class Person // ... public void getGehalt { // lokale Hilfsklasse zur Berechnung class GehaltsRechnerHilfsklasse extends GehaltsRechner { // ... } } } Folie 52 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Anonyme Klassen Im Prinzip namenlose Klassen Werden in der Form eines Ausdrucks definiert: new Vaterklasse(Parameter) { Klassenrumpf }; Können keine Konstruktoren haben Sind nur dann sinnvoll, wenn Ö sie klein sind (Empfehlung: nicht mehr als 4 Zeilen) Ö der Name ohne Belang ist Ö nur eine Instanz benötigt wird Verwendung insbesondere in der AWT/Swing-Programmierung se Person p = new Person() { public void gehaltErhoehen() { gehalt = 0; } }; // dieses Semikolon beendet die new-Anweisung p.setGehalt(7000); p.gehaltErhoehen(); Folie 53 © 2004-2006, Rainer Schmidberger, ISTE Teil 3: Die Klassen des JDK se Datum und Zeit Sammlungsklassen Formatierung Dateizugriffe 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Übersicht: Datum und Zeit Calendar (from ut il) Serializable (from io) Date (from util) Time Date (from sql) (from sql) Timestamp Programmentwicklung, Vorlesungsskript (from sql) GregorianCalendar se (from util) Calendar(arg0 : TimeZone, arg1 : Locale) Calendar() getInstance() : Calendar getInstance(arg0 : TimeZone) : Calendar getInstance(arg0 : Locale) : Calendar getInstance(arg0 : TimeZone, arg1 : Locale) : Calendar getAvailableLocales() : Locale[] computeTime() : void computeFields() : void getTime() : Date setTime(arg0 : Date) : void getTimeInMillis() : long setTimeInMillis(arg0 : long) : void get(arg0 : int) : int internalGet(arg0 : int) : int internalSet(arg0 : int, arg1 : int) : void set(arg0 : int, arg1 : int) : void set(arg0 : int, arg1 : int, arg2 : int) : void set(arg0 : int, arg1 : int, arg2 : int, arg3 : int, arg4 : int) : void set(arg0 : int, arg1 : int, arg2 : int, arg3 : int, arg4 : int, arg5 : int) : void clear() : void clear(arg0 : int) : void isSet(arg0 : int) : boolean complete() : void equals(arg0 : Object) : boolean hashCode() : int before(arg0 : Object) : boolean after(arg0 : Object) : boolean add(arg0 : int, arg1 : int) : void roll(arg0 : int, arg1 : boolean) : void roll(arg0 : int, arg1 : int) : void setTimeZone(arg0 : TimeZone) : void getTimeZone() : TimeZone setLenient(arg0 : boolean) : void isLenient() : boolean setFirstDayOfWeek(arg0 : int) : void getFirstDayOfWeek() : int setMinimalDaysInFirstWeek(arg0 : int) : void getMinimalDaysInFirstWeek() : int getMinimum(arg0 : int) : int getMaximum(arg0 : int) : int getGreatestMinimum(arg0 : int) : int getLeastMaximum(arg0 : int) : int getActualMinimum(arg0 : int) : int getActualMaximum(arg0 : int) : int clone() : Object toString() : String Ab JDK 1.1 wird zur Behandlung von Datum-Werten die Klasse Calendar bzw. GregorianCalender verwendet. Paket java.util Klasse util.Date mit den Kindklassen sind wird wegen fehlender Zeitzonen weitestgehend nicht mehr zu verwenden (depricated). Folie 55 Konstruktor mit Jahr, Monat (Achtung 0..11) und Tag Methode setTime mit Date-Übergabe Arithmetik, Vergleiche 08.03.2007 // der 09.12.2003 GregorianCalendar d1 = new GregorianCalendar(2006, 11, 9); String s1 = "Jahr: " + d1.get(Calendar.YEAR)); String s2 = "Monat: " + d1.get(Calendar.MONTH); // Achtung: 0 - 11 String s3 = "Tag: " + d1.get(Calendar.DATE)); Programmentwicklung, Vorlesungsskript © 2004-2006, Rainer Schmidberger, ISTE Klasse GregorianCalendar Calendar d2 = Calendar.getInstance(); int tag = d2.get(Calendar.DAY_OF_WEEK); // So = 0, Mo = 1, ... if(d1.before(d2)) { // d1 liegt vor d2 } se Folie 56 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Datum - Formatierung Die Formatierung eines Datums in einen String erfolgt über die Klasse DateFormat oder SimpleDateFormat import java.text.DateFormat; // ... GregorianCalendar heute = Calendar.getInstance(); String s1 = DateFormat.getTimeInstance().format(heute.getTime()); String s2 = DateFormat.getDateInstance().format(heute.getTime()); String s3 = DateFormat.getDateTimeInstance(). format(heute.getTime()); SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd ** HH:mm"); String s4 = sd.format(heute.getTime()); // // // // se s1 s2 s3 s4 = = = = 16:01:59 25.02.2005 25.02.2005 16:01:59 2005-02-25 ** 16:01 Folie 57 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Datum - Arithmetik Die Methode add ermöglicht die Addition und Subtraktion von Zeitspannen Die Einheit der Zeitspanne wird über den ersten Parameter der Methode add festgelegt (YEAR, MONTH, WEEK, DATE, ...) GregorianCalendar g = new GregorianCalendar(2002, 11, 9); // +3 Monate g.add(Calendar.MONTH, 3); // -> 09.03.2003 // -12 Tage g.add(Calendar.DATE, -12); // -> 25.02.2003 se Folie 58 double-Formatierung import java.text.*; // ... double d1 = 40.98382; double d2 = 1293; double d3 = -4039.8; DecimalFormat df = new DecimalFormat("#,##0.00;(#,##0.00)"); System.out.println(df.format(d1)); System.out.println(df.format(d2)); System.out.println(df.format(d3)); Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Formatierungen String s1 = "3.920,09" Number n1 = df.parse(eingabe); double d4 = n1. doubleValue(); Ausgabe im lokalisierten Format se 40,98 1.293,00 (4.039,80) Optionales Sub-pattern für negative Zahlen Folie 59 String fileSeparator = System.getProperty("file.separator"); Weitere Schlüssel: java.version, java.class.path, os.name, os.version, user.name, user.dir, file.separator, path.separator, line.separator, ... Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Properties der Klasse System se Folie 60 Writer CharArrayWriter (from io) (f ro m i o) lock : Object PrintWriter (from io) PrintWriter(arg0 : OutputStream, arg1 : boolean) PrintWriter(arg0 : OutputStream) PrintWriter(arg0 : Writer, arg1 : boolean) PrintWriter(arg0 : Writer) flush() : void close() : void checkError() : boolean setError() : void write(arg0 : int) : void write(arg0 : char[], arg1 : int, arg2 : int) : void write(arg0 : char[]) : void write(arg0 : String, arg1 : int, arg2 : int) : void write(arg0 : String) : void print(arg0 : boolean) : void print(arg0 : char) : void print(arg0 : int) : void print(arg0 : long) : void print(arg0 : float) : void print(arg0 : double) : void print(arg0 : char[]) : void print(arg0 : String) : void print(arg0 : Object) : void println() : void println(arg0 : boolean) : void println(arg0 : char) : void println(arg0 : int) : void println(arg0 : long) : void println(arg0 : float) : void println(arg0 : double) : void println(arg0 : char[]) : void println(arg0 : String) : void println(arg0 : Object) : void Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Übersicht Writer se Writer(arg0 : Object) Writer() write(arg0 : int) : void write(arg0 : char[]) : void write(arg0 : char[], arg1 : int, arg2 : int) : void write(arg0 : String) : void write(arg0 : String, arg1 : int, arg2 : int) : void flush() : void close() : void FilterWrit er (from io) PipedWriter (from io) StringWriter (f ro m i o) OutputStreamWriter BufferedWriter (f ro m i o) (f ro m i o) OutputStreamWriter(arg0 : OutputStream, arg1 : CharsetEncoder) OutputStreamWriter(arg0 : OutputStream, arg1 : Charset) OutputStreamWriter(arg0 : OutputStream) OutputStreamWriter(arg0 : OutputStream, arg1 : String) getEncoding() : String flus hBuffer() : void write(arg0 : int) : void write(arg0 : char[], arg1 : int, arg2 : int) : void write(arg0 : String, arg1 : int, arg2 : int ) : void flus h() : void close() : void BufferedWriter(arg0 : Writer, arg1 : int) BufferedWriter(arg0 : Writer) flushBuffer() : void write(arg0 : int) : void write(arg0 : char[], arg1 : int, arg2 : int) : void write(arg0 : String, arg1 : int, arg2 : int) : void newLine() : void flush() : void close() : void FileWriter (from io) FileWriter(arg0 : FileWriter(arg0 : FileWriter(arg0 : FileWriter(arg0 : FileWriter(arg0 : FileDescriptor) File, arg1 : boolean) File) String, arg1 : boolean) String) Folie 61 In Textdatei abspeichern Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: Textdatei schreiben se Person familieDuck[] familieDuck[0] = new familieDuck[1] = new familieDuck[2] = new = Person[3]; Person("Tick", 5, 456.6); Person("Trick", 6, 451.9); Person("Track", 7, 411.2); PrintWriter out = new PrintWriter(new BufferedWriter( new FileWriter("c:/dummy/personenDaten.txt"))); for(int i = 0; i < 3; i++) { Person p = familieDuck[i]; out.println(p.getName() + "\t" + Integer.toString(p.getAlter()) + "\t" + Double.toString(p.getGehalt())); } out.close(); Folie 62 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Übersicht: Reader se Reader (from io) StringReader lock : Object (from io) Reader(arg0 : Object) Reader() read() : int read(arg0 : c har[]) : int read(arg0 : c har[], arg1 : int, arg2 : int) : int skip(arg0 : long) : long ready() : boolean markSupported() : boolean mark(arg0 : int) : void res et() : void close() : void FilterReader (from io) CharArrayReader (from io) PipedReader (from io) InputStreamReader (from io) InputStreamReader(arg0 : InputStream, arg1 : CharsetDecoder) InputStreamReader(arg0 : InputStream, arg1 : Charset) InputStreamReader(arg0 : InputStream, arg1 : String) InputStreamReader(arg0 : InputStream) getEncoding() : String read() : int read(arg0 : char[], arg1 : int, arg2 : int) : int ready() : boolean close() : void FileReader (f rom io ) FileReader(arg0 : FileDescriptor) FileReader(arg0 : File) FileReader(arg0 : String) BufferedReader (f rom i o) BufferedReader(arg0 : Reader) BufferedReader(arg0 : Reader, arg1 : int) read() : int read(arg0 : char[], arg1 : int, arg2 : int) : int readLine(arg0 : boolean) : String readLine() : String skip(arg0 : long) : long ready() : boolean markSupported() : boolean mark(arg0 : int) : void reset() : void close() : void Folie 63 Aus Textdatei auslesen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: Textdatei lesen se BufferedReader in = new BufferedReader( new FileReader("c:/dummy/personenDaten.txt")); String zeile; while((zeile = in.readLine()) != null) { StringTokenizer st = new StringTokenizer(zeile, "\t"); int zustand = 0; String name = new String(); int alter = 0; double gehalt = 0; while(st.hasMoreTokens()) { String token = st.nextToken(); switch(zustand) { case 0: name = token; break; case 1: alter = Integer.parseInt(token); break; case 2: gehalt = Double.parseDouble(token); break; } zustand++; } Person p = new Person(name, alter, gehalt); p.out(); Es wird jeweils eine vollständige Zeile eingelesen. Klasse StringTokenizer dient als Hilfsklasse eine Zeilenstruktur auszuwerten } in.close(); Folie 64 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Übersicht: InputStream InputStream (from io) System (from lang) +$in StringBufferInputStream (from io) InputStream() read() : int read(arg0 : byte[]) : int read(arg0 : byte[], arg1 : int, arg2 : int) : int skip(arg0 : long) : long available() : int close() : void mark(arg0 : int) : void reset() : void markSupported() : boolean Byt eArrayInputStream (from io) FileInputStream (from io) Programmentwicklung, Vorlesungsskript Object InputSt ream se (from io) FileInputSt ream(arg0 : FileDescriptor) FileInputSt ream(arg0 : File) FileInputSt ream(arg0 : String) read() : int read(arg0 : byt e[]) : int read(arg0 : byt e[], arg1 : int, arg2 : int) : int sk ip(arg0 : long) : long available() : int close() : void getFD() : FileDescript or getChannel() : FileChannel finalize() : void Folie 65 © 2004-2006, Rainer Schmidberger, ISTE Übersicht: OutputStream FilterOutput Stream OutputStream (from io) (f rom io ) #out OutputStream() write(arg0 : int) : void write(arg0 : byte[]) : void write(arg0 : byte[], arg1 : int, arg2 : int) : void flush() : void close() : void PipedOutputStream (from io) ByteArray Out putSt ream (f ro m i o) PrintStream (f rom i o) Object Output Stream (f rom i o) FileOutputStream Programmentwicklung, Vorlesungsskript 08.03.2007 (from io ) se FileOutputStream(arg0 : FileDescriptor) FileOutputStream(arg0 : File, arg1 : boolean) FileOutputStream(arg0 : File) FileOutputStream(arg0 : String, arg1 : boolean) FileOutputStream(arg0 : String) write(arg0 : int) : void write(arg0 : byte[]) : void write(arg0 : byte[], arg1 : int, arg2 : int) : void close() : void getFD() : FileDescriptor getChannel() : FileChannel finalize() : void +$out +$err SocketOutputStream (from net) System (f rom l ang) PrintStream(arg0 : OutputStream, arg1 : boolean, arg2 : String) PrintStream(arg0 : OutputStream, arg1 : boolean) PrintStream(arg0 : OutputStream) flush() : void close() : void checkError() : boolean setError() : void write(arg0 : int) : void write(arg0 : byte[], arg1 : int, arg2 : int) : void print(arg0 : boolean) : void print(arg0 : char) : void print(arg0 : int) : void print(arg0 : long) : void print(arg0 : float) : void print(arg0 : double) : void print(arg0 : char[]) : void print(arg0 : String) : void print(arg0 : Object) : void println() : void println(arg0 : boolean) : void println(arg0 : char) : void println(arg0 : int) : void println(arg0 : long) : void println(arg0 : float) : void println(arg0 : double) : void println(arg0 : char[]) : void println(arg0 : String) : void println(arg0 : Object) : void Folie 66 Objekte mit ihren Objektbeziehungen in Dateien speichern und laden Objekte speichern sich Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Serialisierung (1) se Objekte werden instanziert und laden sich Folie 67 Generische Implementierung für Laden und Speichern der Attribute eines Objektes Automatisch "richtige" Instanzierung als Objekt der entsprechenden Klasse beim Laden Es ist das leere Interface Serializable zu "implementieren". Bei speziell berechneten Attributen writeObject und readObject implementieren Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Serialisierung (2) se Class Person implements Serializable { private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); // ... Hier weitere Implementierung ... } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); // ... Hier weitere Implementierung ... } } Folie 68 Objekte speichern Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Serialisierung (3) se Person donald = new Person(); Programmierer trick = new Programmierer(); Person daisy = new Person(); // ... FileOutputStream in = new FileOutputStream( "c:/dummy/testdaten.dat"); ObjectOutputStream s = new ObjectOutputStream(in); s.writeObject(donald); s.writeObject(trick); s.writeObject(daisy); s.flush(); s.close(); Folie 69 Objekte laden Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Serialisierung (4) se FileInputStream in = new FileInputStream( "c:/dummy/testdaten.dat"); ObjectInputStream s = new ObjectInputStream(in); Person p = (Person)s.readObject(); p.out(); p = (Person)s.readObject(); p.out(); p = (Person)s.readObject(); p.out(); s.close(); Type-cast erforderlich, da formal die Objekte vom Typ Object geliefert werden. Folie 70 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Klasse File se File (from io) File(arg0 : URI) File(arg0 : File, arg1 : String) File(arg0 : String, arg1 : String) File(arg0 : String) getPrefixLength() : int getName() : String getParent() : String getParentFile() : File getPath() : String isAbsolute() : boolean getAbsolutePath() : String getAbsoluteFile() : File getCanonicalPath() : String getCanonicalFile() : File toURL() : URL toURI() : URI canRead() : boolean canWrite() : boolean exists() : boolean isDirectory() : boolean isFile() : boolean isHidden() : boolean lastModified() : long length() : long createNewFile() : boolean delete() : boolean deleteOnExit() : void list() : Logical View::java::lang::String[] list(arg0 : FilenameFilter) : Logical View::java::lang::String[] listFiles() : File[] listFiles(arg0 : FilenameFilter) : File[] listFiles(arg0 : FileFilter) : File[] mkdir() : boolean mkdirs() : boolean renameTo(arg0 : File) : boolean setLastModified(arg0 : long) : boolean setReadOnly() : boolean listRoots() : File[] createTempFile(arg0 : String, arg1 : String, arg2 : File) : File createTempFile(arg0 : String, arg1 : String) : File compareTo(arg0 : File) : int compareTo(arg0 : Object) : int equals(arg0 : Object) : boolean hashCode() : int toString() : String java.io.File Hilfsklasse zur Verwaltung von Dateien wie z.B Ö Verzeichnisse anlegen Ö Pfade ermitteln Ö ... Folie 71 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Threads (1) Ein Thread ist ein leichtgewichtiger Prozess ohne eigenen Speicherraum Java-Programme können mehrere Threads parallel haben Threads kennen drei Zustände: aktiv (running), inaktiv (suspended), tot (dead) run() ist die main-Methode eines Threads (siehe Interface Runnable) Start eines Threads mit start(), hierdurch wird run() gestartet Der Thread läuft bis zum Ende von run() Implementierung erfolgt als Kindklasse von Thread oder über Implementierung des Interface Runnable und Verwendung des entsprechenden Konstruktors von Thread Synchronisation von Methoden über Schlüsselwort synchronized Je Thread kann eine Priorität gesetzt werden (setPriority()) se Folie 72 public static void main(String[] args) { class PersonThread extends Thread { Person person; public PersonThread(Person p) { person = p; } public void run() { for(int i = 0; i < 100; i++) { person.updateAlter(); System.out.println("Alter: " + person.getAlter()); } } } Person donald = new Person(); 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Threads (2) Programmentwicklung, Vorlesungsskript PersonThread t1 = new PersonThread(donald); PersonThread t2 = new PersonThread(donald); t1.start(); t2.start(); Klasse PersonThread als Kindklasse von Thread. Methode run() implementiert die Funktionalität des Threads. Instanzieren der Threads. } se Starten der Threads. Folie 73 Unsynchronisiert, aber kurzzeitig Programmentwicklung, Vorlesungsskript public void updateAlter() { int a = getAlter(); setAlter(a + 1); } Unsynchronisiert, langdauernd 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Threads (3) public void updateAlter() { int a = getAlter(); try { Thread.currentThread().sleep(1000); } catch(InterruptedException e) {} setAlter(a + 1); Alter: Alter: Alter: Alter: ... 1 2 3 4 Alter: Alter: Alter: Alter: Alter: Alter: ... 1 1 2 2 3 3 Alter: Alter: Alter: Alter: Alter: ... 1 2 3 4 5 } synchronisiert, langdauernd se synchronized public void updateAlter() { int a = getAlter(); try { Thread.currentThread().sleep(1000); } catch(InterruptedException e) {} setAlter(a + 1); } Folie 74 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Sammlungsklassen Zentrale Interfaces: Collection und Map Die Collection-Klassen des JDK implementieren das Interface Collection und haben Array-Funktionalität Sind gegenüber den Arrays aber flexibler und mächtiger Auf Collections wird über einen Iterator zugegriffen Grundsätzlich findet bei den Collections eine Unterteilung in Set und List statt. Die Map-Klassen bilden Schlüssel (keys) auf Werte (values) ab. Schlüssel können Strings, Integer oder auch Objektreferenzen sein Überwiegend aus java.util se Folie 75 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Collection se <<Interface>> Collection size() : int isEmpty() : boolean contains(arg0 : Object) : boolean iterator() : Iterator toArray() : Object[] toArray(arg0 : Object[]) : Object[] add(arg0 : Object) : boolean remove(arg0 : Object) : boolean containsAll(arg0 : Collection) : boolean addAll(arg0 : Collection) : boolean removeAll(arg0 : Collection) : boolean retainAll(arg0 : Collection) : boolean clear() : void equals(arg0 : Object) : boolean hashCode() : int <<Interface>> List size() : int isEmpty() : boolean contains(arg0 : Object) : boolean iterator() : Iterator toArray() : Logical View::java::lang::Object[] toArray(arg0 : Logical View::java::lang::Object[]) : Logical View::java::lang::Object[] add(arg0 : Object) : boolean remove(arg0 : Object) : boolean containsAll(arg0 : Collection) : boolean addAll(arg0 : Collection) : boolean addAll(arg0 : int, arg1 : Collection) : boolean removeAll(arg0 : Collection) : boolean retainAll(arg0 : Collection) : boolean clear() : void equals(arg0 : Object) : boolean hashCode() : int get(arg0 : int) : Object set(arg0 : int, arg1 : Object) : Object add(arg0 : int, arg1 : Object) : void remove(arg0 : int) : Object indexOf(arg0 : Object) : int lastIndexOf(arg0 : Object) : int listIterator() : ListIterator listIterator(arg0 : int) : ListIterator subList(arg0 : int, arg1 : int) : List Ein Objekt kann mehrfach enthalten sein <<Interface>> Set size() : int isEmpty() : boolean contains(arg0 : Object) : boolean iterator() : Iterator toArray() : Logical View::java::lang::Object[] toArray(arg0 : Logical View::java::lang::Object[]) : Logical View::java::lang::Object[] add(arg0 : Object) : boolean remove(arg0 : Object) : boolean containsAll(arg0 : Collection) : boolean addAll(arg0 : Collection) : boolean retainAll(arg0 : Collection) : boolean removeAll(arg0 : Collection) : boolean clear() : void equals(arg0 : Object) : boolean hashCode() : int Ein Objekt kann nur einfach enthalten sein Folie 76 AbstractCollection AbstractSequentialList (from util) public abstract Object get(int index) Abst ractSet AbstractList (from util) (from util) Collection ArrayList (from Arrays) 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Übersicht Collection SubLis t (f ro m ut il) Programmentwicklung, Vorlesungsskript (from util) (f ro m ut il) Vector se HashSet ArrayList (from util) List Set (from ut il) (from util) LinkedHashSet (from util) Stack TreeSet (f ro m ut il) (from util) SortedSet Ein Objekt kann mehrfach enthalten sein (from util) Ein Objekt kann nur einfach enthalten sein Folie 77 public static void main(String[] args) { Person Person Person Person Person Programmentwicklung, Vorlesungsskript p1 p2 p3 p4 p5 = = = = = new new new new new Person("Donald", 45, 456); Person("Tick", 45, 52); Person("Trick", 45, 54); Person("Track", 45, 56); Person("Dagober", 45, 70000); Vector v = new Vector(); v.add(p1); v.add(p2); v.add(p3); v.insertElementAt(p4, 1); v.add(p5); v.remove(2); 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: Vector java.util.* Klasse Vector ist eine Alternative zu Arrays Vorteil: Vector kann dynamisch wachsen Einfügungen sind leicht möglich Iterator ermöglicht einfaches iterieren über einen Vector Iterator iterator = v.iterator(); while(iterator.hasNext()) { Person p = (Person)iterator.next(); p.out(); } } se Folie 78 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Interface: Comparable TreeSet treeset = new TreeSet(); treeset.add(donald); treeset.add(daisy); treeset.add(tick); treeset.add(trick); treeset.add(track); Iterator i = treeset.iterator(); while(i.hasNext()) { Person p = (Person)i.next(); p.out(); } // ... class Person implements Comparable { // ... public int compareTo(Object o) { Person p1 = this; Person p2 = (Person) o; // return p1.getAlter() - p2.getAlter(); return p1.getName().compareTo(p2.getName()); } } se java.util.Comparable Klassen, die das Interface Comparable implementieren, definieren eine Sortierreihenfolge Die Kollektion TreeSet verwendet dieses Interface zur Sortierung der dort eingestellten Einträge Siehe auch Interface Comparator (hier wird eine separate Klasse erstellt, die die Sortierung festlegt) Ausgabe des Beispiels: Name: Name: Name: Name: Name: Daisy Donald Tick Track Trick Alter: Alter: Alter: Alter: Alter: 46 42 4 7 6 Progspr.: Java Folie 79 HashIterator Ent ryIterat or Link edHashIterator <<Int erface>> Iterator EmptyIterator Typischer Anwendungsfall: hasNext() next() remove() Vector v = new Vector(); // ... Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Iterator Iterator iterator = v.iterator(); while(iterator.hasNext()) { Object o = iterator.next(); // ... } Die speziellen Implementierungen sind nicht bedeutsam se IdentityHashMapIterator <<Interface>> ListIterator hasNext() next() hasPrevious() previous() nextIndex() previousIndex() remove() set() add() It r ListItr Folie 80 © 2004-2006, Rainer Schmidberger, ISTE Übersicht Map WeakHashMap (from util) Dictionary IdentityHashMap Abs tractMap NOTE: This class is obsolete. New implementations should implement the Map interface, rather than extendidng this class. (from util) (f ro m ut il) (from util) Hashtable 08.03.2007 (from util) HashMap Programmentwicklung, Vorlesungsskript SubMap se (f ro m ut il) Map (from TreeMap) (from util) Properties TreeMap (from util) (f rom ut il) SortedMap (from util) Folie 81 <<Interface>> Map size() : int isEmpty() : boolean containsKey(arg0 : Object) : boolean containsValue(arg0 : Object) : boolean get(arg0 : Object) : Object put(arg0 : Object, arg1 : Object) : Object remove(arg0 : Object) : Object putAll(arg0 : Map) : void clear() : void keySet() : Set values() : Collection entrySet() : Set equals(arg0 : Object) : boolean hashCode() : int Das Interface Map ist das zentrale Interface der Klassen, die Schlüssel (keys) auf Werte (values) abbilden Siehe besonders: Ö put Ö get Bedeutsame Implementierung: Ö Hashtable Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Map se Folie 82 public static void main(String[] args) { Person Person Person Person Person Programmentwicklung, Vorlesungsskript p1 p2 p3 p4 p5 = = = = = new new new new new Person("Donald", 45, 456); Person("Tick", 45, 52); Person("Trick", 45, 54); Person("Track", 45, 56); Person("Dagober", 45, 70000); Hashtable t = new Hashtable(); t.put(p1.getName(), p1); t.put(p2.getName(), p2); t.put(p3.getName(), p3); t.put(p4.getName(), p4); 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: Hashtable Person p = (Person)t.get("Donald"); p.out(); p = (Person)t.get("Track"); p.out(); java.util.* Klasse Hashtable stellt eine indizierte Liste dar Vorteil: sehr schneller Zugriff Hilfsklasse um Eindeutigkeiten herzustellen Achtung: falls ein Schlüssel mit get() nicht gefunden wird, wird null zurückgeliefert } se Folie 83 se © 2004-2006, Rainer Schmidberger, ISTE Teil 4: JavaDoc 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JavaDoc (1) Etablierte Programmcode Dokumentationsmethode für Java HTML Generierung innerhalb der IDE oder die Anwendung Ö javadoc [ options ] [ packagenames ] [ sourcefilenames ] [ subpackages pkg1:pkg2:... ] [ @argfiles ] Das JDK ist auf diese Weise dokumentiert JavaDoc Tags Soll eine optische Aufbereitung erfolgen, muss in die Kommentierung HTML mit aufgenommen werden Programmentwicklung, Vorlesungsskript http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html se Folie 85 /** * Helper method to load the object given by the object ID. See, that table name * is automatically detected by the metaclass info within the object ID. * * @param oid the object ID to load * @param refresh true: refresh object in any case, false: do not refresh object in any case (only if expired) * @see ObjectDepot * * @return the entire object. The class depends on the OID */ static public PObject loadObject(String oid, boolean refresh) { // ... } Automatische Generierung Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JavaDoc (2) se Folie 86 @author name Adds an "Author" entry with the specified name-text to the generated docs when the -author option is used @deprecated deprecated-text Adds a comment indicating that this API should no longer be used @exception classname description The @exception tag is a synonym for @throws @param parameter-name description Adds a parameter to the "Parameters" section. The description may be continued on the next line. This tag is valid only in a doc comment for a method or constructor @return description Adds a "Returns" section with the description text. This text should describe the return type and permissible range of values. @see reference Adds a "See Also" heading with a link or text entry that points to reference @see "string" @see <a href="URL#value">label</a> @see package.class#member label Adds a "Since" heading with the specified since-text to the generated documentation Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JavaDoc Tags @since since-text @throws classname description @version version-text The @throws and @exception tags are synonyms. Adds a "Throws" subheading to the generated documentation, with the class-name and description text. Adds a "Version" subheading with the specified version-text to the generated docs when the -version option is used Quelle: Sun Microsystems se Folie 87 © 2004-2006, Rainer Schmidberger, ISTE Einschub: Java 5 (Tiger) Erweiterungen Rainer Schmidberger [email protected] se Generics Erweiterte for-Schleifen Aufzählungstypen Autoboxing/Unboxing (Implizite Typwandlung) Variable Argumenten-Liste Statische Importe Annotationen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Java 5 Erweiterungen se Folie 89 Definition einer generischen Klasse class A<T> { private T t; Vector<T> liste = new Vector<T>(); public T getT() { return t; } Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Generische Klassen (Generics) public void setT(T t) { this.t = t; } Instanzierung einer generischen Klasse A<String> a1 = new A<String>(); A<Calendar> a2 = new A<Calendar>(); a1.setT("Hallo"); a2.setT(Calendar.getInstance()); // Generische Klassen aus dem JDK (hier // Vektor von String) Vector<String> v1 = new Vector<String>(); // Vektor von String-Vektoren Vector<Vector<String>> v2 = new Vector<Vector<String>>(); // ... } se Folie 90 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Generics und Subtyping Erweiterung einer generischen Klasse class A<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } } class B<T> extends A<T> { // ... } se Instanzierung A<String> a1 = new B<String>(); // OK A<String> a2 = new A<String>(); a2.setT("Hallo"); A<Object> a3 = a2; // nicht OK! // Aber mit "wildcards" A<?> a4 = a2; Object o1 = a4.getT(); // OK // OK, -> Hallo a3.setT("Test"); // nicht OK Folie 91 class K // ... } A<K> a1 = new A<K>(); K k1 = a1.getT(); // OK // OK A<?> a2 = a1; // OK K k2 = a2.getT(); // // // // // Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Bounded wildcards se nicht OK, da a2 als wildcard und damit auf Object typisiert ist // Abhilfe: bounded wildcards A<? extends K> a3 = a1; K k3 = a3.getT(); // OK Folie 92 Form: for(FormalParameter : Expression) statement , wobei Expression das Interface Iterable implementieren muss Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Erweiterte for-Schleife se Vector<Person> personenListe = ...; Iterator<Person> i = personenListe.iterator(); while(i.hasNext()) { Person p = i.next(); // ... } for(Person p : personenListe) { // ... } // erweiterte for-Scheife bei Feldern int[] zahlen = new int[10]; for(int zahl : zahlen) { system.out.println(zahl); } Folie 93 java.lang.Iterable java.util.Collection implementiert Iterable public interface Iterable<E> { public Iterator<E> iterator(); } Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Interface Iterable se Folie 94 Definieren einen Referenztyp (wie eine Klasse) Definieren je Aufzählung ein statisches Objekt enum AmpelFarbe Programmentwicklung, Vorlesungsskript se { rot, gelb, gruen }; public static void enumTest() { AmpelFarbe startFarbe = AmpelFarbe.rot; AmpelFarbe farbe2 = 1; 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Aufzählungstypen (1) // OK // Nicht OK for(AmpelFarbe farbe : AmpelFarbe.values()) { System.out.println("Ampelfrabe: " + farbe + "\tName: " + farbe.name() + "\tOrdinal: " + farbe.ordinal()); } } Ampelfrabe: rot Ampelfrabe: gelb Ampelfrabe: gruen Name: rot Name: gelb Name: gruen Ordinal: 0 Ordinal: 1 Ordinal: 2 Folie 95 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Aufzählungstypen (2) se AmpelFarbe farbe1 = AmpelFarbe.valueOf("gelb"); // OK // wirft IllegalArgumentException AmpelFarbe farbe2 = AmpelFarbe.valueOf("lila"); // Exception // Verwendung in Fallunterscheidung switch(farbe1) { case rot: System.out.println("Es war rot"); break; case gelb: System.out.println("Es war gelb"); break; case gruen: System.out.println("Es war gruen"); break; } Folie 96 Autoboxing/Unboxing Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Implizite Typwandlung se int a = 22; Integer b = a; // int -> Integer a = b; // Integer -> int Vector<Integer> integerListe = new Vector<Integer>(); integerListe.add(b); integerListe.add(a); integerListe.add(33); int c = integerListe.elementAt(1); Object o1 = 33; Object o2 = 33.0; // Typwandlung in Integer // Typwandlung in Double Folie 97 Beispiel: Methode printf von PrintStream Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Variable Argumentenliste se public static void variableAruments(Object ... args) { for(Object o : args) { System.out.println("Argument: " + o); } } public static void variableAruments(String, Object ... args) { // ... } // Aufruf variableAruments(22, Calendar.getInstance(), new Integer(4)); variableAruments("Hallo", Calendar.getInstance(), new Integer(4)); Folie 98 Import statischer Methoden oder Attribute Verwendung ohne qualifizierenden Bezeichner Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Statische Importe se package beispiel; public class KonstantenBeispiel { public static int KONSTANTE_1 = 1; public static int KONSTANTE_2 = 7; // ... } import static beispiel.KonstantenBeispiel.*; class XY { void eineMethode() { int einWert = KONSTANTE_1; // anstelle von // KonstantenBeispiel.KONSTANTE_1 // ... } } Folie 99 Anmerkungen zum Code, die keine Semantik hinsichtlich der Code-Funktionalität enthalten Ähnlich @depricated oder auch „transient“ Annotationen können zum „kommentieren“ von Code verwendet werden. Die Kommentare sind aber Teil des Syntax-Baumes. Vorgesehener Verwendungszweck Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Annotationen se Ö Vermeiden von zusätzlichen Konfigurationsdateien Ö Unterstützung Code-generierender Werkzeuge import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) // Verbleib im Bytecode // legt fest, dass Methoden // annotiert werden public @interface Entwickler { // definiert neue Annotation // mit den Namen "Entwicker" String name(); String vorname(); } Folie 100 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Annotieren von Code se public class Person { // ... @Entwickler(name = "Albert", vorname = "Einstein") public double getGehalt() { return gehalt; } // ... } Person p = new Person("Tick", 300); for (Method m : p.getClass().getMethods()) { if (m.isAnnotationPresent(Entwickler.class)) { Entwickler e = m.getAnnotation(Entwickler.class); System.out.println(m.getName() + " ist entwickelt von " + e.vorname() + " " + e.name()); } } getGehalt ist entwickelt von Albert Einstein Folie 101 se © 2004-2006, Rainer Schmidberger, ISTE Teil 5: GUI-Programmierung Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE AWT und Swing Seit Java 1.2 stehen zwei Möglichkeiten zur GUIProgrammierung zur Verfügung: AWT (Abstract Window Toolkit) und die Swing Bibliothek AWT nutzt die GUI Komponenten des Betriebssystems. Es stehen daher nur die gemeinsame Schnittmenge der verschiedenen Betriebssysteme zur Verfügung. Konkret fehlen Tabellen oder Bäume. AWT-Anwendungen sehen auf den verschiedenen Betriebssystemen verschieden aus. Swing „zeichnet“ seine GUI Komponenten alle selbst. Somit sehen Swing-Anwendungen unter verschiedenen Betriebssystemen auch weitestgehend gleich aus. Der Performance Nachteil von Swing spielt heute kaum mehr eine Rolle, d.h. die Vorteile von Swing gegenüber AWT überwiegen. Swing erweitert in vielen Fällen die AWT Klassen se Folie 103 © 2004-2006, Rainer Schmidberger, ISTE Swing Container Übersicht Component (from awt) paintingChild 0..* +component parent Container (from awt) Window 08.03.2007 (from awt) Dialog Panel ScrollPane (from awt) (from awt) Frame (from awt) (from awt) menuBar MenuBar JTabbedPane (from awt) Programmentwicklung, Vorlesungsskript (from swing) JComponent JScrollBar (from s wing) JDialog JWindow JFrame (from swing) (from swing) (from swing) se (from swing) JPanel (from swing) JMenuBar JOptionPane (from swing) (from swing) Folie 104 © 2004-2006, Rainer Schmidberger, ISTE JFrame JFrame oder JDialog gehören zu den Top-Level Komponenten JFrame JRootPane Die JLayeredPane enthält eine (optionale) Menüleiste 08.03.2007 JLayeredPane Content-Pane Programmentwicklung, Vorlesungsskript Glass-Pane Die Content-Pane enthält die Bildschirmelemente se Die Glass-Pane ist üblicherweise unsichtbar und kann Oberflächenereignisse filtern Folie 105 Klasse DialogBeispiel als Kindklasse von JFrame. public class DialogBeispiel extends JFrame { Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JFrame-Beispiel (1) JButton buttonSpiegeln = new JButton(); JLabel jLabel1 = new JLabel(); JLabel jLabel2 = new JLabel(); JTextField eingabe = new JTextField(); JTextField ausgabe = new JTextField(); Je Bildschirmelement entsteht ein eigenes Attribut. // ... } se Folie 106 // ... Programmentwicklung, Vorlesungsskript Konstruktor public DialogBeispiel() { buttonSpiegeln.setBounds( new Rectangle(305, 19, 164, 36)); buttonSpiegeln.setText("Spiegeln"); 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JFrame-Beispiel (2) jLabel1.setText("Eingabe:"); jLabel1.setBounds( new Rectangle(14, 19, 107, 17)); // ... } ... se Eigenschaften der „Components“ werden gesetzt Positionierung der „Components“ wird gesetzt Folie 107 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JFrame-Beispiel (2) Klasse DialogBeispiel als Kindklasse von JFrame. public class DialogBeispiel extends JFrame { JButton buttonSpiegeln = new JButton(); JLabel jLabel1 = new JLabel(); JLabel jLabel2 = new JLabel(); JTextField eingabe = new JTextField(); JTextField ausgabe = new JTextField(); // ... static void main(String args[]) { DialogBeispiel d = new DialogBeispiel(); d.setVisible(true); } public DialogBeispiel() { // .. addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } se Je Bildschirmelement entsteht ein eigenes Attribut. Ein Objekt der JFrameKindklasse wird instanziert und sichtbar gemacht. Das Ereignis "windowClosing" soll die Anwendung beenden Folie 108 javax.swing.JComponent 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Übersicht: JComponent AbstractButton JMenuItem JLabel JMenu JToggleButton JToolTip JRadioButton JPanel JButton JCheckBox Programmentwicklung, Vorlesungsskript JOptionPane se JTextComponent JEditorPane JScrollPane JTabbedPane JTextField JTextArea Folie 109 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Das Listener-Prinzip se Listener ist mit dem Button verbunden und "hört" dort auf Ereignisse Listener-Objekt Durch die Implementierung der Methode actionPerformed wird wieder eine Methode des JFrameKindkklassen-Objekts aufgerufen Ereignisse wie MausKlick oder Tastatureingaben buttonSpiegeln.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { buttonSpiegeln_actionPerformed(e); } }); // ... void buttonSpiegeln_actionPerformed(ActionEvent e) { StringBuffer b1 = new StringBuffer(eingabe.getText()); b1.reverse(); String s1 = new String(b1); ausgabe.setText(s1); } Folie 110 DefaultListModel listModelLinien = new DefaultListModel(); JScrollPane jScrollPane1 = new JScrollPane(); JList liste = new JList(listModelLinien); Liste ist in eine ScrollPane eingebettet. ListenModell Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Listbox void buttonInListe_actionPerformed(ActionEvent e) { String s1 = eingabe.getText(); listModelLinien.addElement(s1); } se Das ListenModell hat je Listenzeile ebenso einen Objekt-Eintrag. Über die toStringMethode erfolgt die Anzeige Das ListenModell benachrichtigt die Listbox eigenständig Folie 111 Repräsentieren boolsche Werte Können in Gruppen (CheckboxGroup) gruppiert werden Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Checkbox se void checkBoxAuswerten_actionPerformed(ActionEvent e) { String text = new String(); if(jCheckBox1.isSelected()) text += "Einen "; if(jCheckBox2.isSelected()) text += "schönen "; if(jCheckBox3.isSelected()) text += "guten "; if(jCheckBox4.isSelected()) text += "Tag"; editAusgabe.setText(text); } // Checkbox selektieren: jCheckBox2.setSelected(true) Folie 112 Werden üblicherweise gruppiert (in einer ButtonGroup) Können ein Ereignis bei Selektion auslösen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Radiobutton se JRadioButton radioButtonNormal = new JRadioButton(); JRadioButton radioButtonDisable = new JRadioButton(); JRadioButton radioButtonHide = new JRadioButton(); ButtonGroup gruppe = new ButtonGroup(); // ... gruppe.add(radioButtonNormal); gruppe.add(radioButtonDisable); gruppe.add(radioButtonHide); // ... void radioButtonDisable_actionPerformed(ActionEvent e) { listbox.setEnabled(false); listbox.setVisible(true); jScrollPane1.setEnabled(false); jScrollPane1.setVisible(true); } Folie 113 Ähnlich einer Single-Selection Listbox Als Default-Modell dient eine Object-Referenz Zum eingestellten Objekt wird (wie immer in solchen Fällen) die toString-Methode zur Anzeige verwendet Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Combobox se JComboBox comboBox = new JComboBox(); //... comboBox.addItem("Montag"); comboBox.addItem("Dienstag"); comboBox.addItem("Mittwoch"); comboBox.addItem("Donnerstag"); comboBox.addItem("Freitag"); comboBox.addItem("Samstag"); comboBox.addItem("Sonntag"); // ... void comboBox_actionPerformed(ActionEvent e) { String text = (String)comboBox.getSelectedItem(); editAusgabe.setText(text); } Folie 114 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JPanel graphisch unsichtbarer Container kann als Ganzes in einen anderen Container eingebettet werden (z.B. JTabbedPane) Container für Komponenten Ö add-Methoden Ö getComponentCount() Ö getComponent(int) hat Layout-Manager (default: FlowLayout) se Ö setLayout(LayoutManager) Folie 115 wie Panel ein Container hat Titel Ö setTitle(String) kann Menü haben Ö setMenuBar(MenuBar) kann minimiert, größenverändert, aktiviert werden Ö setIconImage(Image) Ö setResizable(boolean) Ö toFront() / toBack() Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Frame hat Layout-Manager (default: BorderLayout) Ö setLayout(LayoutManager) erzeugt WindowEvent wichtigste Methoden: pack() und show() se Folie 116 Sorgen für die Anordnung von Komponenten in einem Container (bei jeder Veränderung, z.B. Öffnen, Resize) Implementieren das Interface LayoutManager Vordefinierte Layout-Manager: Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE LayoutManager (1) se Ö BorderLayout: nach Himmelsrichtungen (South=unten, etc.) (default bei Windows) Ö CardLayout: Karteikarten, die übereinander liegen Ö FlowLayout: in einer Reihe, notfalls umbrechen (default bei Panels) Ö GridLayout: auf zweidimensionalem Raster Ö GridBagLayout: auf zweidimensionalem Raster, Ö Randbedingungen sehr präzise mit Hilfe von GridBagConstraints spezifizierbar (kompliziert) Folie 117 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE LayoutManager (2) Einem Container ist ein LayoutManager zugeordnet panel.setLayout(new BorderLayout()); Komponenten werden durch add-Methoden dem Container hinzugefügt add-Methoden unterscheiden sich je nach verwendetem Layoutmanager in den Parametern, bei BorderLayout: panel.add("North", new Button("North")); panel.add("Center", new Button("Center")); Container überträgt die Anordnung der Komponenten seinem Layoutmanager (kein direkter Aufruf durch den Programmierer!) se Folie 118 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Menuitems JMenuBar menueleiste = new JMenuBar(); JMenu menu1 = new JMenu(); JMenu menu2 = new JMenu(); JMenuItem menuItemBeenden = new JMenuItem(); JMenuItem menuItemSpiegeln = new JMenuItem(); menu1.setText("Datei"); menuItemBeenden.setText("Beenden"); menu2.setText("Bearbeiten"); menuItemSpiegeln.setText("Spiegeln"); menuItemSpiegeln.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { menuItemSpiegeln_actionPerformed(e); } }); menueleiste.add(menu1); menueleiste.add(menu2); menu1.add(menuItemBeenden); menu2.add(menuItemSpiegeln); setJMenuBar(menueleiste); se Anonyme Klasse als "ActionListener" des Menuitems Folie 119 Ermöglicht das Aufteilen von Komponenten auf mehrere Seiten Je Seite wird ein Panel angelegt public class Panel1 extends JPanel { JLabel jLabel1 = new JLabel(); JTextField jTextField1 = new JTextField(); // ... } 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JTabbedPane Programmentwicklung, Vorlesungsskript JTabbedPane tabbedPane = new JTabbedPane(); // ... se Panel1 panel1 = new Panel1(); Panel2 panel2 = new Panel2(); tabbedPane.addTab("Erster Panel", panel1); tabbedPane.addTab("Zweiter Panel", panel2); Folie 120 se © 2004-2006, Rainer Schmidberger, ISTE Teil 6: Applet-Programmierung Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Applet Java-Programm, das eingebettet im Browser abläuft erbt von java.applet.Applet Methoden zur Ablaufsteuerung (geerbt): public void init() Ö wird zu Beginn aufgerufen (einmalige Initialisierungen) public void start() Ö wird zum Starten des Applets aufgerufen public void stop() Ö wird zum Stoppen des Applets aufgerufen public void destroy() se Ö wird zum Schluß aufgerufen (Aufräumarbeiten) Applet laden init Applet darstellen Seite verlassen start stop Seite aufrufen Seite verwerfen destroy Folie 122 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Aufbau des APPLET-Tags <APPLET CODE=Applet-Datei WIDTH=pixel HEIGHT=pixel [CODEBASE=URL für Code] [ARCHIVE=JAR-Datei(en)] [ALT=alternativer Text, z.B. wenn Java deaktiviert] [NAME=Referenzname der Appletinstanz] [ALIGN=Ausrichtung, z.B. left, top, middle] [VSPACE=pixel] [HSPACE=pixel] > [{<PARAM NAME=ParamName VALUE=ParamWert>}] [alternativer HTML-Text für nicht-java-fähige Browser] </APPLET> se Folie 123 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel-HTML Seite <html> <head> <title> SpiegelDialog Testseite </title> </head> <body> Hier wird nun der SpiegelDialog angezeigt: <br> <applet codebase = "." code = "SpiegelDialog.class" name = "TestApplet" width = "500" height = "200" hspace = "0" vspace = "0" align = "middle" > </applet> </body> </html> se Folie 124 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Sandbox Das alles ist in der Sandbox verboten: Dateisystem Ö Dateien lesen, schreiben, löschen, umbenennen, auf Existenz prüfen, Informationen abfragen (z.B. Größe) Ö Verzeichnisse anlegen, löschen, umbenennen, anzeigen Netzwerk Ö Verbindung zu anderen Rechnern (Ausnahme: Server) Lokale Umgebung Ö System Properties abfragen, anlegen Ö Programme ausführen Manipulation der Sandbox (z.B. SecurityManager) und der Laufzeitumgebung (z.B. ClassLoader) se Folie 125 se © 2004-2006, Rainer Schmidberger, ISTE Teil 7: JDBC-Programmierung Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JDBC Java Database Connectivity Standardverfahren um von Java aus auf (in der Regel relationale) Datenbanken zuzugreifen SQL-Anweisungen werden auf diese weise an die Datenbank übermittelt Rückgabeergebnisse - speziell bei SELECT-Abfragen können leicht ausgewertet werden Datenbanken bieten direkt eine JDBC-Schnittstelle an oder aber indirekt über ODBC se Datenbank JavaAnwendung JDBCSchnittstelle ODBCSchnittstelle Folie 127 // für MS-Access oder andere ODBC-Quelle mit Name "TestDatabase" Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection connection = java.sql.DriverManager.getConnection("jdbc:odbc:TestDatabase", "", ""); Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JDBC Verbindung zur Datenbank // Alternativ:Zugriff auf Oracle8 mit Instanzname "TestDB" DriverManager.registerDriver (new oracle.jdbc.OracleDriver ()); connection = DriverManager.getConnection("jdbc:oracle:oci8:@TestDB", "TestUser", "logon"); se Folie 128 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JDBC SELECT-Abfrage (1) Connection connection = … siehe Folie "JDBC Verbindung zur Datenbank" … Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery( "SELECT name, email, type from person"); while(resultSet.next()) { name = resultSet.getString(1); email = resultSet.getString(2); type = resultSet.getInt(3); // irgendwie die Werte weiterverwenden Programmentwicklung, Vorlesungsskript } SQL ausführen Über Ergebnismenge iterieren Aus der Ergebnismenge die Spaltenwerte entnehmen resultSet.close(); statement.close(); connection.close(); se Folie 129 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JDBC SELECT-Abfrage (2) Connection connection = … siehe Folie "JDBC Verbindung zur Datenbank" … PreparedStatement statement = connection.prepareStatement ("SELECT name, email, type from person WHERE type = ?"); // nur Personen des Typs 2 suchen statement.setInt(1, 2); ResultSet = statement.executeQuery(); while(resultSet.next()) { name = resultSet.getString(1); email = resultSet.getString(2); type = resultSet.getInt(3); Programmentwicklung, Vorlesungsskript // irgendwie die Werte weiterverwenden se } resultSet.close(); statement.close(); connection.close(); Folie 130 Absenden beliebiger SQL-Anweisungen SQL wird vollständig als String aufgebaut (Achtung: Hochkomma aus SQL-Syntax für Stringkonstanten beachten) Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JDBC Update se Connection connection = … siehe Folie "JDBC Verbindung zur Datenbank" … Statement statement = connection.createStatement(); // Beispiel Update statement.executeUpdate("Update person Set " + "name = '" + p.getName() + "', " + "email = '" + p.getEMail() + "', " + "type = " + String.valueOf(p.getType()) + ", " + "' where oid = '" + p.getOID() + "'"); // Beispiel Insert statement.executeUpdate("INSERT INTO person (oid, name, email, type) " + "VALUES (" + "'" + p.getOID() + "', " + "'" + p.getName() + "', " + "'" + p.getEMail() + "', " + String.valueOf(p.getType())); Folie 131 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JDBC (3) se Absenden beliebiger SQL-Anweisungen mit Platzhaltern Platzhalter werden einzeln mit Werten besetzt Vorteil: Übersicht, Datenformate, Datenbankperformance setString, setInt, setBoolean, setTimestamp Connection connection = … siehe Folie "JDBC Verbindung zur Datenbank" … try { // Beispiel Update Statement statement = connection. prepareStatement( "Update person Set name = ?, email = ?, type = ? where oid = ?"); statement.setString(1, "Müller"); statement.setString(2, "[email protected]"); statement.setInt(3, 2); statement.setString(4, "12345"); statement.executeUpdate(); statement.close(); connection.commit(); } catch(Exception e) { connection.rollback(); } Folie 132 © 2004-2006, Rainer Schmidberger, ISTE Einführung Java 2 Enterprise Edition (J2EE) Rainer Schmidberger [email protected] se Servlets und JSP (Java Server Page) Enterprise JavaBeans (EJB) Java Naming and Directory InterfaceTM API JDBCTM API JavaMailTM API CORBA Compliance Java Transaction API XML Deployment Descriptors Java Message Service Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE J2EE Inhalt Quelle: Sun Microsystems se Folie 134 Standardisiertes Architekturmodell für serverbasierte Java-Anwendungen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE J2EE application model Quelle: Sun Microsystems se Folie 135 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Java Anwendungsarten se Java-Application SwingOberfläche Java-Applet SwingOberfläche als Applet AnwendungsLogik Java VM Laden der Anwendung von Lokales Laufwerk AnwendungsLogik Sandbox im Browser J2EE: Java-Servlet / JSP HTMLOberfläche Browser Servlet/JSP AnwendungsLogik Web-Server Laden der Anwendung von Laden der Anwendung von WebServer WebServer Folie 136 Statisch abgelegte Dokumente wie z.B. HTML-Seiten werden von Web Server an den User übermittelt HTTP request Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Statisches Web HTTP response Statische Dokumente (HTML) se Web Server Browser User Folie 137 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Dynamisches Web Web Seiten werden im Application-Server dynamisch, d.h. im Moment der Anfrage, erzeugt Web Server HTTP request HTTP response Statische Dokumente (HTML) HTTP request: Parameter HTTP response: Dynamischer Inhalt Browser Programmentwicklung, Vorlesungsskript Beispiel für einen Servlet-Container: se Servlet oder JSP Datenbank http://jakarta.apache.org/tomcat/index.html Application Server, ServletContainer Folie 138 Der Web-Browser sendet Parameter im Request über den Servlet-Container zum Servlet Servlet-Container Request Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Request-Response Prinzip se Servlet Geschäftslogik: Implementierung in „Standard“ Java Response Das Servlet erstellt die Folgeseite und liefert diese im Response an den Browser zurück Folie 139 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Was sind Servlets? Servlets sind Objekte, deren Klasse das Interface javax.servlet.Servlet implementiert Servlets werden innerhalb eines Servlet-Containers (oder auch Servlet Engine) instanziert und gestartet Häufigste Verwendung als HTTPServlet, das auf BrowserAnfragen (Request) antwortet Servlets bekommen vom Client (dem Browser) Parameter im Request-Objekt übergeben Servlets erzeugen HTML-Code, der als Response zum Client zurückgeliefert wird Servlet-Container sind Application-Server, die die J2EE Spezifikation erfüllen. Bekannte Hersteller hierfür sind Bea (WebLogic), IBM (WebSphere), Apache (Tomcat, JBoss, OpenSource), Enterprise Server (Borland), ... se Folie 140 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Aufgaben des Servlet se Request Servlet-Aufgabe Teil 1: Ausführen der Tätigkeiten, die durch den Request angefordert sind Z.B. Geschäftslogik starten, Daten speichern usw... Servlet-Aufgabe Teil 2: Erzeugen der folgenden HTML-Seite Dieses Erzeugen findet über das ResponseObjekt statt Response Folie 141 © 2004-2006, Rainer Schmidberger, ISTE doGet und doPost Parameterübergabe per „get“ doGet 08.03.2007 Ö Parameter sind in der URL des Aufrufs enthalten Ö Aufruf kann mit den Parametern „gebookmarked“ werden Request Programmentwicklung, Vorlesungsskript Parameterübergabe per „post“ se Ö Parameter sind nicht in der URL des Aufrufs sondern als Tabelle eingebettet im Request enthalten Ö Nur für Formulare verwendbar Request doPost Folie 142 Request Servlet void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Implementierung des Servlet se // … request-Objekt auswerten: String parameter1 = request.getParameter("parameter1") // response-Objekt befüllen response.getWriter().println("Hello World"); } Response Folie 143 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Interface Servlet se <<Interface>> Servlet (from servlet) destroy() : void getServletConfig() : ServletConfig getServletInfo() : String init(servletconfig : ServletConfig) : void service(servletrequest : ServletRequest, servletresponse : ServletResponse) : void GenericServlet (from servlet) <<Interface>> JspPage GenericServlet() destroy() : void getInitParameter(name : String) : String getInitParameterNames() : Enumeration getServletConfig() : ServletConfig getServletContext() : ServletContext getServletInfo() : String getServletName() : String init() : void init(config : ServletConfig) : void log(msg : String) : void log(message : String, t : Throwable) : void service(servletrequest : ServletRequest, servletresponse : ServletResponse) : void (from jsp) jspDestroy() : void jspInit() : void <<Interface>> Serializable (from io) HttpServlet (from http) HttpServlet() <<ServletdoDelete>> doDelete(req : HttpServletRequest, resp : HttpServletResponse) : void <<ServletdoGet>> doGet(req : HttpServletRequest, resp : HttpServletResponse) : void <<ServletdoOptions>> doOptions(req : HttpServletRequest, resp : HttpServletResponse) : void <<ServletdoPost>> doPost(req : HttpServletRequest, resp : HttpServletResponse) : void <<ServletdoPut>> doPut(req : HttpServletRequest, resp : HttpServletResponse) : void <<ServletdoTrace>> doTrace(req : HttpServletRequest, resp : HttpServletResponse) : void getLastModified(req : HttpServletRequest) : long <<ServletService>> service(req : ServletRequest, res : ServletResponse) : void <<ServletService>> service(req : HttpServletRequest, resp : HttpServletResponse) : void Besonders wichtige Methoden: doPost doGet Folie 144 © 2004-2006, Rainer Schmidberger, ISTE Interface ServletRequest <<Interface>> ServletRequest (from servlet) (from http) getAttribute(s : String) : Object getAttributeNames() : Enumeration getCharacterEncoding() : String getContentLength() : int getContentType() : String getInputStream() : ServletInputStream getLocale() : Locale getLocales() : Enumeration getParameter(s : String) : String getParameterNames() : Enumeration getParameterValues(s : String) : String[] getProtocol() : String getReader() : BufferedReader getRealPath(s : String) : String getRemoteAddr() : String getRemoteHost() : String getRequestDispatcher(s : String) : RequestDispatcher getScheme() : String getServerName() : String getServerPort() : int isSecure() : boolean removeAttribute(s : String) : void setAttribute(s : String, obj : Object) : void 08.03.2007 Programmentwicklung, Vorlesungsskript <<Interface>> HttpServletRequest Ö Bitte beachten: Spezifiziert sind hier nur Interface. Die Implementierung ist Sache des Application-Server Herstellers. se getAuthType() : String getContextPath() : String getCookies() : Cookie[] getDateHeader(s : String) : long getHeader(s : String) : String getHeaderNames() : Enumeration getHeaders(s : String) : Enumeration getIntHeader(s : String) : int getMethod() : String getPathInfo() : String getPathTranslated() : String getQueryString() : String getRemoteUser() : String getRequestURI() : String getRequestedSessionId() : String getServletPath() : String getSession() : HttpSession getSession(flag : boolean) : HttpSession getUserPrincipal() : Principal isRequestedSessionIdFromCookie() : boolean isRequestedSessionIdFromURL() : boolean isRequestedSessionIdFromUrl() : boolean isRequestedSessionIdValid() : boolean isUserInRole(s : String) : boolean Besonders wichtige Methoden: getParameter getCookies getSession Folie 145 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Interface ServletResponse se <<Interface>> ServletResponse <<Interface>> HttpServletResponse (from http) (from servlet) flushBuffer() : void getBufferSize() : int getCharacterEncoding() : String getLocale() : Locale getOutputStream() : ServletOutputStream getWriter() : PrintWriter isCommitted() : boolean reset() : void setBufferSize(i : int) : void setContentLength(i : int) : void setContentType(s : String) : void setLocale(locale : Locale) : void addCookie(cookie : Cookie) : void addDateHeader(s : String, l : long) : void addHeader(s : String, s1 : String) : void addIntHeader(s : String, i : int) : void containsHeader(s : String) : boolean encodeRedirectURL(s : String) : String encodeRedirectUrl(s : String) : String encodeURL(s : String) : String encodeUrl(s : String) : String sendError(i : int) : void sendError(i : int, s : String) : void sendRedirect(s : String) : void setDateHeader(s : String, l : long) : void setHeader(s : String, s1 : String) : void setIntHeader(s : String, i : int) : void setStatus(i : int) : void setStatus(i : int, s : String) : void Besonders wichtige Methoden: getWriter addCookie Ö Bitte beachten: Spezifiziert sind hier nur Interface. Die Implementierung ist Sache des Application-Server Herstellers. Folie 146 import import import import javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*; public class ServletTest extends HttpServlet { public void init() throws ServletException { } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); out.println("Hello World"); } 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE "Hello World" Servlet Programmentwicklung, Vorlesungsskript } Zusammenhang zwischen HTTPAdresse und Servlet-Klassenname wird über eine Konfigurationsdatei (web.xml) hergestellt se Folie 147 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Formulare <html> <head><title>ServletTest</title></head> <body> <form method=post action=servlettest> Eingabe: <input type=text name=Eingabe /> <br> Ausgabe: ... Hier berechneten Wert einsetzen <br> <br> <input type=submit name=Submit /> </form> </body></html> Typisch sind Formulare zur Dateneingabe HTML-Tag: <form ..> ... </form> HTML kann beliebig zur Gestaltung genutzt werden Inhalte der Eingabefelder werden i. Allg. per "post" an den Server übermittelt und können dort aus dem Request-Objekt ausgewertet werden Absenden mit "Submit" Button Das unter "action=" festgelegte Servlet wird gestartet se Aufruf des Servlets und Parameterübergabe Die Folge-Seite wird vom aufgerufenen Servlet wieder produziert Folie 148 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Methode "doPost" //Process the HTTP Post request public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); String ausgabe = request.getParameter("Eingabe"); // post-Parameter if(ausgabe == null) ausgabe = ""; // auswerten out.println("<html>"); out.println("<head><title>ServletTest</title></head><body>"); out.println("<form method=post>"); out.println("Eingabe:"); out.println("<input type=text name=Eingabe />"); // Parametername out.println("<br>Ausgabe:"); // definieren out.println(reverse(ausgabe)); out.println("<br><br>"); out.println("<input type=submit name=Submit />"); out.println("</form></body></html>"); out.close(); } se Folie 149 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Lebenszyklus Server lädt und kreiert Instanz von ServletTest Ö Methode void init () Interaktion mit Clients (Behandlung von Anfragen) Ö GenericServlet • void service (ServletRequest, ServletResponse) Ö HttpServlet • void doGet (HttpServletRequest, HttpServletResponse) • void doPost (HttpServletRequest, HttpServletResponse) Server entfernt Servlet-Instanz (beim Stoppen des Servers) se Ö Methode void destroy () Folie 150 Paket: javax.servlet.http Enthält Informationen über die übergebenen Parameter und den aufrufenden Client Parameter Informationen Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Request Objekt (1) se Ö String getParameter (String) Liefert den Wert eines konkreten Parameters. Ö Enumeration getParameterNames () Liefert die Namen sämtlicher Parameter, die im requestObjekt mitgeliefert wurden. Ö String[] getParameterValues (String) Diese Methode ist für Parameter geeignet, die mehr als einen Wert enthalten können. Zurückgeliefert wird ein ganzes Array von Werten des benannten Parameters. Folie 151 Client Informationen Ö String getRemoteAddr () Liefert die IP-Adresse des Client. Ö String getRemoteHost () Damit wird der voll qualifizierte Name des Client bestimmt. Ö Das Interface javax.servlet.http.HttpServletRequest enthält weitere häufig benutzte Methoden zur Behandlung von HTTP-Anfragen. Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Request Objekt (2) se Folie 152 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Das Response-Objekt Paket: javax.servlet.http Kapselt die gesamte Kommunikation zum Client Ö Response-Objekt wird vom Servlet-Container generiert Zugriff auf Ö Header Ö OutputStream- bzw. Writer-Objekte • • Writer für textbasierte Daten OutputStream für binäre Daten Möglichkeit zum se Ö Setzen von Cookies Ö Weiterleiten von Anfragen Ö Senden von Fehlerseiten Folie 153 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Cookies (1) Ein Server kann Daten in ein "Cookie" speichern und dieses zum Client senden. Bei jedem Client-Request werden die Cookies vom Browser zurück an den Server gesendet, insofern die URL die gleiche ist. Ein Cookie dient zur Identifizierung des Clients oder der Sitzung Cookies haben im wesentlichen einen Namen und einen Inhalt (z.B. Name: "UserID", Wert: "007") Die Klasse javax.servlet.http.Cookie im Servlet API bietet unterstützung bei der Verwendung von Cookies se Folie 154 Cookies werden über seinen Namen identifiziert (Methode getName()) Der Inhalt eines Cookie ist vom Typ String (Methode getValue()) Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Cookies (2) se Cookie cookies[] = request.getCookies(); for(int i = 0; i < cookies.length; i++) { Cookie cookie = cookies[i]; if(cookie.getName().equals("Erste Eingabe")) { out.println("<br>Erste Eingabe: " + cookie.getValue()); } } if(cookies.length == 0 && ausgabe != null) { Cookie cookie = new Cookie("Erste Eingabe", ausgabe); response.addCookie(cookie); } Folie 155 Jeder Benutzer erhält ein javax.servlet.http.HttpSession Objekt in dem Daten pro Sitzung gespeichert werden können. Daten (Object) werden über einen Namen (String) in die Session gespeichert und über diesen Namen wieder gelesen. Basisdatentypen wie z.B. int werden über die zugeordnete Klasse behandelt Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Sitzungen se public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ... HttpSession session = request.getSession(); if(session.isNew()) { out.println("Willkomen, Sie sind ein neuer User"); session.setAttribute("AmountVisited", new Integer(1)); } else { Integer i = (Integer)session.getAttribute("AmountVisited"); session.setAttribute("AmountVisited", new Integer(i.intValue() + 1)); out.println("Sie sind zum " + i + ". mal auf dieser Seite."); } // ... Folie 156 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Deployment Eine Web Applikation ist ein Sammlung von Servlets, JSP Seiten, HTML Dokumenten, Bilder sowie die Konfigurationsdatei web.xml Alle Dateien einer Web Applikation können in einem WebArchive (war-Datei) zusammen gefasst werden. Die Datei web.xml wird als Deployment Descriptor bezeichnet. web.xml enthält Konfigurations Informationen für den Server über die Web Applikation. web.xml wird im folgenden Verzeichnis gespeichert: server_root/webapps/<myWebApp>/WEB-INF Die Struktur von web.xml entspricht dem XML Standard se <?xml version="1.0" encoding="UTF-8"?> <web-app> <servlet> <servlet-name>helloworld</servlet-name> <servlet-class>HelloWorld</servlet-class> </servlet> ... </web-app> Folie 157 Problematik bei Servlets Ö Vermischung von Präsentation und Verarbeitungslogik Ö Designer-Werkzeuge für HTML nicht verwendbar Abhilfe: Java Server Pages (JSP) Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Java Server Page se Ö Konzipiert für Web-Seiten mit dynamisch generiertem Inhalt Ö Weiterentwicklung von Servlets Ö Striktere Trennung von fachlicher Logik und Präsentation Ö Änderungen im Inhalt unabhängig von Verarbeitungslogik Ö Vereinfachung der Seitenentwicklung durch Tags Ö Funktionalität für dynamische Inhalte ist in Tags gekapselt Ö Verwendung wiederverwendbarer Komponenten Ö Komponenten (z.B. JavaBeans) realisieren fachliche Verarbeitung Folie 158 <html><head><title>JSPTest</title></head> <h1>Spiegel Java Server Page</h1> <body> <form method="post"> Eingabe: <input type=text name=eingabe /> <br>Ausgabe: <%! // eine Deklaration String eingabe, ausgabe; %> <% // hier steht nun Java-Code ... eingabe = request.getParameter("eingabe"); Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Einfache JSP Was fällt soweit auf? Aussehen ähnlich einem statischen HTML-Dokument. Einbettung von Java-Code über <% ... %> Deklarationen über <%! ... %> out und request stehen ohne Deklaration zur Verfügung. if(eingabe != null) { ausgabe = ServletTest.reverse(eingabe); out.println(ausgabe); } // Ende des Java-Codes %> <input type=submit name=Submit /> </form></body></html> se Folie 159 Zu einer JSP kann es ein JavaBean geben. Die Verbindung wird mit dem Tag <jsp:useBean ... /> vorgenommen. Die Lebensdauer einer Bean-Instanz legt scope= "page|request|session|application" fest Die Instanzierung erfolgt mit dem ersten Öffnen der JSP Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JSP und JavaBeans se <html><head><title>JSPTest</title></head> <h1>Spiegel Java Server Page</h1> <jsp:useBean id="jspTestBean" scope="session" class="JSPTestBean" /> <body> <form method="post"> Eingabe: <input type=text name=eingabe /> <br> Ausgabe: <%! String ausgabe; %> <% jspTestBean.setEingabe(request.getParameter("eingabe")); ausgabe = jspTestBean.getReverseEingabe(); out.println(ausgabe); %> <br><br> <input type=submit name=Submit /> </form></body></html> Folie 160 // die Bean-Klasse: public class JSPTestBean { String eingabe = ""; public String getEingabe() { return eingabe; } public void setEingabe(String s) { eingabe = s; } 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JavaBean public String getReverseEingabe() { return ServletTest.reverse(eingabe); } Programmentwicklung, Vorlesungsskript } se Ist eine "normale" Java-Klasse Kann in einem beliebigen Paket liegen Kann in einer beliebigen Vererbungshierarchie sein Hat jeweils eine setAbc und eine getAbc-Methode, wobei der Name des Property "abc" ist Beispiel: setEingabe/getEingabe ergeben das Property "eingabe" (Achtung: kleiner Anfangsbuchstabe) Weitere Methoden können beliebig hinzugefügt werden Folie 161 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JSP und JavaBeans (2) <html><head><title>JSPTest</title></head> <h1>Spiegel Java Server Page</h1> <jsp:useBean id="jspTestBean" scope="session" class="JSPTestBean" /> <jsp:setProperty name="jspTestBean" property="*"/> <body> <form method="post"> Eingabe: <input type=text name=eingabe /> <br> Ausgabe: <%! String ausgabe; %> <% ausgabe = jspTestBean.getReverseEingabe(); out.println(ausgabe); %> <br>Eingabe war: <jsp:getProperty name="jspTestBean" property="eingabe"/> <br><br> <input type=submit name=Submit /> </form></body></html> se Die Properties eines JavaBeans können fest mit den Parametern des RequestObjektes verbunden werden Feste PropertyBenennung oder "*" für alle Properties Folie 162 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Weitere Direktiven Include Direktive Ö Syntax: <%@ include file="relativeURL" %> Ö Fügt Inhalt einer statischen oder dynamischen Datei in JSPDatei ein Forward Direktive Ö Syntax: <jsp:forward page=“{ relativeURL | <%= Ausdruck %> }“ /> Ö Leitet Client-Anfrage an HTML-Datei, JSP-Datei oder Servlet zur Verarbeitung weiter Taglib Direktive se Ö Syntax: <%@ taglib uri=“TagBibliothekURI“ prefix=“tagPräfix“ %> Ö Definiert Bibliothek für eigene Tags und des dabei verwendeten Präfix Folie 163 1. Deklarationen Ö Ö Ö Ö Programmentwicklung, Vorlesungsskript Syntax: <%! ... %> Dient zur Deklaration von Variablen und Methoden Jede Deklaration wird durch ein Semikolon abgeschlossen Beispiel: <%! int i = 0; %> 2. Ausdrücke (engl. Expressions) 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JSP – Scripting Elements se Ö Ö Ö Ö Ö Ö Syntax: <%= ... %> Kann beliebige (gültige) Ausdrücke enthalten Ausdrücke werden nicht durch ein Semikolon abgeschlossen Werden zur Laufzeit ausgewertet und durch Wert ersetzt Der ermittelte Wert wird immer in einen String konvertiert Beispiel: a + b = <%= a + b %> Folie 164 Scriptlets 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JSP – Scripting Elements (Forts.) Ö Syntax: <% ... %> Ö Scriptlets können jeden beliebigen (gültigen) Java-Code enthalten Ö Ausdrücke werden durch ein Semikolon abgeschlossen Ö Dienen zur Implementation der fachlichen Logik von JSPs Ö Es stehen implizite Variablen zur Verfügung Ö Beispiel: <% Programmentwicklung, Vorlesungsskript eingabe = request.getParameter("eingabe"); se if(eingabe != null) { ausgabe = ServletTest.reverse(eingabe); out.println(ausgabe); } %> Folie 165 Variablen, die ohne Deklaration in Scripting-Elementen verwendbar sind 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Implizite Variablen Ö request (Unterklasse von javax.servlet.ServletRequest) • Ö response (Unterklasse von javax.servlet.ServletResponse) • Programmentwicklung, Vorlesungsskript Antwort der JSP-Seite an den Client Ö out (javax.servlet.jsp.JspWriter) • Servlet Output Writer (Ausgaben an den Client-Browser) Ö session (javax.servlet.http.HttpSession) • HTTP Session Objekt, das mit Anfrage assoziiert wird Ö application (javax.servlet.ServletContext) • se Anfrage des Client (enthält Parameterliste) Servlet Context Objekt (Kommunikation mit dem Servlet Container) Ö config (javax.servlet.ServletConfig) • Das ServletConfig Objekt für die JSP-Seite (enthält z.B. Initialisierungsparameter) Ö exception (java.lang.Throwable) • • Exception, die von der JSP-Seite nicht gefangen wurde. Wird nur in der Fehlerseite des JSPs sichtbar Folie 166 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Kommentare Versteckte Kommentare (Hidden Comment) Ö Syntax: <%-- Kommentar --%> Ö Zum Dokumentieren des Quellkodes Ö Wird von der JSP-Engine nicht verarbeitet und wird somit auch nicht zum Client gesendet Ausgabe Kommentar (Output Comment) se Ö Syntax: <!-- Kommentar [<%= Ausdruck %>] --!> Ö Wird von der JSP-Engine verarbeitet und das Ergebnis taucht in der gesendeten HTML-Quelldatei auf Ö Der im Kommentar enthaltene Ausdruck wird dynamisch zur Laufzeit bei jedem Aufruf evaluiert Folie 167 Das Servlet führt alle Tätigkeiten, die durch den Request angefordert sind, aus. Das Servlet übernimmt keine Darstellungsaufgaben sondern leitet diese an die JSP weiter Die JSP implementiert die Darstellung der Folgeseite. Die Daten zur Darstellung werden dem Bean entnommen, das selbst auf die Geschäftslogik zugreift Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Servlet/JSP–Request/Response (1) se Servlet-Container Request Servlet JSP Geschäftslogik Bean Response Folie 168 Kombination beider Technologien Ö Servlets: Bearbeitung der Anfragen (Geschäftslogik) Ö JSPs: Präsentation der Antworten Ablauf Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Servlet/JSP–Request/Response (2) se Ö Eingehende Anfrage wird von Servlet Engine auf Servlet abgebildet Ö Servlet bearbeitet Anfrage Ö Ermittelte Ergebnisse werden als Attribute in request-Objekt gespeichert Bsp.: request.setAttribute("eingabe", einString); Ö Request-Objekt wird mittels Dispatching-Mechanismus an JSP weitergereicht Ö JSP-Seite liest Attribute aus request-Objekt aus Bsp.: eingabe = (String)request.getAttribute("eingabe"); Ö JSP-Seite bereitet Ergebnisse graphisch auf Ö Erzeugte HTML-Seite wird an Client zurückgeliefert Folie 169 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Servlet/JSP - Dispatching Servlets können JSPs auf zwei Arten aufrufen 1. dispatcher.include() Ö include() ruft eine JSP-Seite auf und wartet auf diese, um mit der Verarbeitung fortzufahren Ö Kann innerhalb eines Servlets mehrmals aufgerufen werden Ö Mechanismus: RequestDispatcher = getServletContext().getRequestDispatcher(“JSP-URI“); dispatcher.include(request, response); 2. dispatcher.forward() se Ö Ö Ö Ö forward() gibt Kontrolle an aufgerufene JSP-Seite weiter Servlet ist danach an Client-Interaktionen nicht mehr involviert Kann innerhalb eines Servlets nur einmal aufgerufen werden Mechanismus: RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(“JSP-URI“); dispatcher.forward(request, response); Folie 170 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Framework Jakarta Struts Jakarta Struts ist ein Framework, das viele Standardaufgaben von JSP/Servlet-Anwendungen bereits enthält So besteht Unterstützung für Ö Mehrsprachigkeit, Internationalisierung Ö Fehlerbehandluch Ö Einfacher Zugriff auf Request Parameter Ö Viele spezielle HTML-Tags für Formulare Umfangreiche Konfigurierungsmöglichkeiten (aber viele XML Dokumente, teilweise nicht einfach bedienbar) Jakarta Struts ist ein Open Source Produkt (http://jakarta.apache.org/struts) se Folie 171 © 2004-2006, Rainer Schmidberger, ISTE XML und Java Rainer Schmidberger [email protected] se Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Was ist XML? <Person PersonalNr="007"> <Name>Müller</Name> <Vorname>Hans</Vorname> <Adresse> <Strasse>Ulmenweg 22</Strasse> <Plz>70565</Plz> <Stadt>Stuttgart</Stadt> </Adresse> </Person> se EXtensible Markup Language XML ist plattformneutral XML ist sprach-unabhängig Strukturierung des XMLDokuments mittels "Tags" Wohlgeformtheit: öffnende und schließende Tags sind symmetrisch angeordnet Beliebig hierarchischer Aufbau Daten und Struktur-Information werden gemeinsam gespeichert Dadurch: "selbsterklärend" "Schablone regelt den Aufbau (DTD=Document Type Definition) Möglichkeit zu Konsistenzregeln Folie 173 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Java – XML DOM: Document Object Model Ö Ö Ö Ö Ö Ö Standardisierung der W3C (www.w3.org/tr) Seit JDK 1.4 in Java enthalten Interface-Sammlung Implementierung erfolgt durch XML-Parser Einfaches Auslesen und Bearbeiten von XML-Dokumenten I/O-Operationen über JAXP (Java API for XML-Processing) SAX: Simple API for XML Parsing Ö Ereignis-basiertes Modell (event based) Ö Mittels "Callback" werden Ereignisse beim Parsen an einen Event-Handler übermittelt JDOM se Ö Ö Ö Ö Java-zentriert, objektorientiert Geringfügige Vereinfachung des DOM API "As simple as Java itself" Java-Sammlungsklassen statt der DOM Node-Klassen Folie 174 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE XML-Dokument <PersonenListe> <Person PersonalNr="007"> <Name>Müller</Name> <Vorname>Hans</Vorname> <Adresse> <Strasse>Ulmenweg 22</Strasse> <Plz>70565</Plz> <Stadt>Stuttgart</Stadt> </Adresse> </Person> <Person PersonalNr="008"> <Name>Mustermann</Name> <Vorname>Annemarie</Vorname> <Adresse> <Strasse>Heilbronnerstr. 44</Strasse> <Plz>70806</Plz> <Stadt>Kornwestheim</Stadt> </Adresse> <Adresse> <Strasse>Piazza di Lago</Strasse> <Plz>I-30672</Plz> <Stadt>Sirmione</Stadt> </Adresse> </Person> </PersonenListe> se Wohlgeformtheit Attribut im öffnenden Tag Person mit zwei Adressen Dokument Folie 175 User Interface Weitere Ausgaben Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE XML Prozessor se Applikation Schnittstelle zwischen Applikation und Prozessor Prozessor Üblicherweise auch als "Parser" bezeichnet Liest XML Dokumente Ermöglicht den Zugriff auf das Dokument Unterscheidung in Validierende und nichtvalidierende Prozessoren Ein-/Ausgabe des XMLDokuments ist Teil der Applikation nicht des Prozessors Die Applikation verwendet den Prozessor Der Prozessor erstellt einen Graphen, der den Dokument Inhalt abbildet XML Dokument Folie 176 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE DOM: Dokument-Baum <PersonenListe> <Person PersonalNr="007"> <Name>Müller</Name> <Vorname>Hans</Vorname> <Adresse> <Strasse>Ulmenweg 22</Strasse> <Plz>70565</Plz> <Stadt>Stuttgart</Stadt> </Adresse> </Person> ... </PersonenListe> Programmentwicklung, Vorlesungsskript getDocumentElement PersonenListe item(...) item(0) 1. Person se Document getFirstChild Name PersonalNr = 007 2. Person getNamedItem("PersonalNr") Vorname getFirstChild Müller item(1) Adresse getNextSibling Hans Folie 177 Knoteninhalt Ö Ö Ö Ö Programmentwicklung, Vorlesungsskript Typ Name Wert Attribute Dokumentstruktur 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE DOM Knoten se Ö Ö Ö Ö Ö Ö Elternknoten Erster Kindknoten Letzter Kindknoten Nächster Geschwisterknoten Voriger Geschwisterknoten Liste aller Kindknoten Folie 178 Paket org.w3c.dom 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE DOM Node-Klassen Node Type : int Name : String Value : String NodeList Element Attr CharacterData NamedNodeMap Document DocumentType DocumentFragment Programmentwicklung, Vorlesungsskript Text se Folie 179 Accessor Methoden Ö getNodeName(), getNodeType(), getNodeValue() Ö setNodeValue(String) Navigation im Dokument Ö getParent(), getFirstChild(), getLastChild(), getPreviousSibling(), getNextSibling() Ö getAttributes : NamedNodeMap Ö getChildNotes() : NodeList Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE DOM API (1) se Folie 180 Änderung eines Dokuments Ö appendChild(Node), insertBefore(Node, Node) Ö replaceChild(node, Node) Ö removeChild(Node) Elemente erzeugen Ö createElement(String), createAttribute(String), createTextNode(String) Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE DOM API (2) se Folie 181 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE javax.xml.parsers // das Factory-Objekt erzeugen DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { // Parser-Objekt durch die Factury erzeugen db = dbf.newDocumentBuilder(); } catch(Exception e) { ... } Document doc = null; try { // Dokument parsen doc = db.parse("PersonenListe.xml"); } catch(Exception e) { ... } // das Dokument auswerten oder bearbeiten Element personenListeElement = doc.getDocumentElement(); NodeList personenNodeList = personenListeElement.getElementsByTagName("Person"); se Folie 182 static private void leseXMLKnoten(Node n) { System.out.print(" Knotenname = " + n.getNodeName()); String val = n.getNodeValue(); if(val != null && !val.equals("")) { System.out.print(" Knotenwert =" + val); } System.out.println(); for(Node kindKnoten = n.getFirstChild(); kindKnoten != null; kindKnoten = kindKnoten.getNextSibling()) { leseXMLKnoten(kindKnoten); } 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE XML als Baum auslesen Baumstruktur des XML-Dokuments legt eine rekursive Auswertung nahe Aber: lineare Auswertung z.B. über alle Kinder eines Knotens ist ebenso möglich Programmentwicklung, Vorlesungsskript } se Folie 183 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE XML linear auslesen Element personenListeElement = doc.getDocumentElement(); NodeList personenNodeList = personenListeElement.getElementsByTagName("Person"); for(int i = 0; i < personenNodeList.getLength(); i++) { Node personNode = personenNodeList.item(i); System.out.println(i + ". Person ----------------------------------"); NodeList personNodeChildNodes = personNode.getChildNodes(); for(int j = 0; j < personNodeChildNodes.getLength(); j++) { Node personElementNode = personNodeChildNodes.item(j); Node personElementNodeValue = personElementNode.getFirstChild(); if(personElementNodeValue != null) { System.out.println(" Knotenname = " + personElementNode.getNodeName() + " Knotenwert = " + personElementNodeValue.getNodeValue()); } } } Ausgabe: se 0. Person ---------------------------------Knotenname = Name Knotenwert = Müller Knotenname = Vorname Knotenwert = Hans Knotenname = Adresse Knotenwert = 1. Person ---------------------------------Knotenname = Name Knotenwert = Mustermann Knotenname = Vorname Knotenwert = Annemarie Knotenname = Adresse Knotenwert = Knotenname = Adresse Knotenwert = Adresse hat nicht einen unmittelbaren "value" Folie 184 © 2004-2006, Rainer Schmidberger, ISTE Unit Tests mit Java Rainer Schmidberger [email protected] se Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Unit-Test Je Klasse entsteht eine eigene Test-Klasse die möglichst alle Methoden testet Ausführung des Tests innerhalb einer Testumgebung Vergleich der Ist- mit den Soll-Resultaten Alle Testklassen werden in einer Test-Suite zusammengefasst XP: Die Testklasse entsteht vor der eigentlichen Klasse und dann wird nur soviel Code geschrieben, wie es der Test erfordert (d.h. fehlerfrei läuft) Testen und codieren läuft in kurzen Iterationsstufen ab (etwa alle 10 min) Alle Sonderfälle, Ausnahmefälle oder Fehlerfälle einer Methode oder eines Objekts werden als Test implementiert se Folie 186 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JUnit www.junit.org Klassen- und Werkzeugsammlung von Kent Beck und Erich Gamma Java-Framework und nur für Java geeignet Trennung von Anwendungs- und Testcode Eigene Klassenhierarchie für Testfälle Zusammenfassung der Tests in Testsuiten Übersichtliche Anzeige der Testergebnisse Ist oft in Entwicklungsumgebungen integriert und als Konsolen- und Swing-Anwendung verfügbar se Folie 187 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JUnit (2) Zusammenhang zwischen Anwendungs- und TestKlasse wird i. Allg. über Namensübereinstimmungen hergestellt Die automatisch gestarteten Methoden der Testklasse müssen mit "test" beginnen Anwendungsklasse: public class Person { Testklasse: public class TestPerson extends TestCase { public void updateAlter() { // ... } public void testUpdateAlter() { // ... } } se } Folie 188 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE JUnit(3) se Auswahl der Testklasse(n) Anzeige des Testprotokolls Anzeige, welche Methoden fehlerfrei abliefen und wo Fehler auftraten Start einzelner TestMethoden Folie 189 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Beispiel: TestPerson import junit.framework.*; public class TestPerson extends TestCase { Person testPerson; public TestPerson(String s) { super(s); } protected void setUp() { testPerson = new Person(); } protected void tearDown() { } public void testSetAlter() { // ... } public void testUpdateAlter() { testPerson.setAlter(30); testPerson.updateAlter(); int neuAlter = testPerson.getAlter(); assertEquals("Achtung: updateAlter fehlerhaft", neuAlter, 31); } } se Ist-Resultat Soll-Resultat Folie 190 © 2004-2006, Rainer Schmidberger, ISTE JUnit Klassendiagramm <<Interface>> TestDecorator Assert assertTrue(b : boolean) assertEquals(b : boolean) <<Interface>> Test countTestCases() : int run(t : TestResult) TestCase run(t : TestResult) 0..* 0..* 08.03.2007 setuP() tearDown() run(t : TestResult) run() AssertionFailedError TestSuite addTest(t : Test) addTestSuite(c : Class) run(t : TestResult) Programmentwicklung, Vorlesungsskript JeweiligeTestklasse se TestResult addListener(t : TestListener) removeListener(t : TestListener) countError() : int failureCount() : int wasSuccessful() : boolean <<Interface>> TestListener addError() 0..* addFailure(t : Test, a : AssertionFailedError) startTest() endTest(Test) Folie 191 Programmentwicklung, Vorlesungsskript 08.03.2007 © 2004-2006, Rainer Schmidberger, ISTE Mock-Objekte Attrappen-Objekte Mock-Objekte ersetzen Objekte der Anwendung und zeigen das selbe Interface Ziel ist die Unabhängigkeit von aufwändiger Infrastruktur wie z.B. Datenbank oder ApplikationsServer Klassen der Mock-Objekte lassen sich in den Entwicklungsumgebungen oftmals automatisch erzeugen Weitere Infos: www.mockobjects.com se Folie 192