Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung ♣ Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 1 Inhalt Advanced Java Serialisierung Remote Method Invocation Servlets Native Methoden Reflexion ♣ Java Beans Enterprise Java Beans Sicherheit Internationalisierung Entwicklungswerkzeuge 2 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung ♣ Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 3 ”Hello-World”-Programm ♣ public class GutenTag { public static void main (String[] argument) { System.out.println ("Guten Tag!"); } } 4 Klassenname, Filenamen GutenTag.java $ javac GutenTag.java GutenTag.class $ java GutenTag Guten Tag! 5 ♣ public static void { } main-Methode ♣ main (String[] argument) 6 Produkt von zwei Zahlen ♣ import java.io.*; public class Produkt { public static void main (String[] argument) { double[] zahl = new double[2]; 7 Produkt von zwei Zahlen for (int i = 0; i < { System.out.print System.out.print System.out.print System.out.flush 2; i++) ("Bitte Zahl "); (i + 1); (" eingeben: "); (); 8 ♣ Produkt von zwei Zahlen try { zahl[i] = new Double ( new BufferedReader ( new InputStreamReader (System.in)) .readLine ()).doubleValue (); // oder ausführlich: //InputStreamReader s = new InputStreamReader (System.in); //BufferedReader t = new BufferedReader (s); //Double d = new Double (t.readLine ()); //zahl[i] = d.doubleValue (); } 9 ♣ Produkt von zwei Zahlen ♣ catch (IOException e) { System.err.println ("IOException wurde geworfen!"); } catch (NumberFormatException e) { System.err.println ("NumberFormatException " + "wurde geworfen!"); } } 10 Produkt von zwei Zahlen System.out.print ("Das Produkt von "); System.out.print (zahl[0]); System.out.print (" mit "); System.out.print (zahl[1]); System.out.print (" beträgt "); System.out.println (zahl[0] * zahl[1]); } } 11 ♣ Produkt von zwei Zahlen ♣ $ javac Produkt.java $ java Produkt Bitte Zahl 1 eingeben: 3.2 Bitte Zahl 2 eingeben: 6 Das Produkt von 3.2 mit 6 beträgt 19.200000000000003 $ 12 import import import Schmier-Programm java.awt.*; java.awt.event.*; javax.swing.*; public class Schmier extends JApplet implements ActionListener, ItemListener, MouseMotionListener { // ... } 13 private private private private private private private Schmier-Programm Container behälter; int altesX = 0; int altesY = 0; Color aktuelleFarbe = Color.black; JButton loeschKnopf; JComboBox farbWahl; JButton endeKnopf; 14 private private private private private static static static static static Schmier-Programm final final final final final String String String String String schwarz = "Schwarz"; rot = "Rot"; gelb = "Gelb"; grün = "Grün"; blau = "Blau"; 15 Schmier-Programm public void init () { behälter = this.getContentPane (); behälter.setLayout (new FlowLayout ()); behälter.setBackground (Color.gray); loeschKnopf = new JButton ("Löschen"); loeschKnopf.addActionListener (this); loeschKnopf.setForeground (Color.black); loeschKnopf.setBackground (Color.lightGray); behälter.add (loeschKnopf); 16 Schmier-Programm farbWahl = new JComboBox (); farbWahl.addItemListener (this); farbWahl.addItem (schwarz); farbWahl.addItem (rot); farbWahl.addItem (gelb); farbWahl.addItem (grün); farbWahl.addItem (blau); farbWahl.setForeground (Color.black); farbWahl.setBackground (Color.lightGray); behälter.add (new JLabel ("Farbe: ")); behälter.add (farbWahl); behälter.addMouseMotionListener (this); } 17 Schmier-Programm public void actionPerformed (ActionEvent ereignis) { Object ereignisQuelle = ereignis.getSource (); if (ereignisQuelle == loeschKnopf) { repaint (); } 18 Schmier-Programm else if (ereignisQuelle == endeKnopf) { System.exit (0); // Nur bei Applikation erlaubt, // bei Applet nicht erlaubt. } } 19 Schmier-Programm public void itemStateChanged (ItemEvent e) { if (e.getItem () == schwarz) aktuelleFarbe = Color.black; else if (e.getItem () == rot) aktuelleFarbe = Color.red; else if (e.getItem () == gelb) aktuelleFarbe = Color.yellow; else if (e.getItem () == grün) aktuelleFarbe = Color.green; else if (e.getItem () == blau) aktuelleFarbe = Color.blue; } 20 Schmier-Programm public void mouseDragged (MouseEvent e) { Graphics g = behälter.getGraphics (); g.setColor (aktuelleFarbe); g.drawLine ( altesX, altesY, e.getX (), e.getY ()); altesX = e.getX (); altesY = e.getY (); } 21 Schmier-Programm public void mouseMoved (MouseEvent e) { altesX = e.getX (); altesY = e.getY (); } 22 Schmier-Programm public void addiere (JComponent komponente) { behälter.add (komponente); } 23 Schmier-Programm public static void main (String[] argument) { Schmier s = new Schmier (); s.init (); s.endeKnopf = new JButton ("Ende"); s.endeKnopf.addActionListener (s); s.endeKnopf.setForeground (Color.black); s.endeKnopf.setBackground (Color.lightGray); s.addiere (s.endeKnopf); 24 Schmier-Programm JFrame f = new JFrame ("Schmier"); f.pack (); // Trick: Erzeugt Peer-Frame f.getContentPane ().add (s, BorderLayout.CENTER); f.setSize (600, 400); s.start (); f.setVisible (true); } 25 Schmier-HTML-Datei <HTML> <HEAD> <TITLE>Das Schmier-Applet</TITLE> </HEAD> <BODY> Wenn Sie einen Java-fähigen Browser benutzen, bitte schmieren Sie im unten angegebenen Applet rum. Ansonsten haben Sie Pech gehabt. <P> <APPLET code="Schmier.class" width=600 height=400> </APPLET> </BODY> </HTML> 26 Schmier-HTML-Datei $ javac Schmier.java $ java Schmier $ appletviewer Schmier.html $ netscape file:‘pwd‘/Schmier.html 27 Geschichte von Java • 1990: James Gosling ”Oak” • 1993: Java-Team (Gosling, Joy, Steele, Tuck, Yellin, van Hoff) • 1995: Erstes Java Developer Kit (JDK 1.0) • 1996: JDK 1.0.2 erste brauchbare Version • 1997: Version JDK 1.1 • 1998: Version JDK 1.2, Java 2 • 1999: Java 2, J2SE, J2ME, J2EE 28 ♣ Merkmale von Java ♣ • Plattformunabhängigkeit (Einsatz in allen möglichen Systemen: Mobiltelefon, Modem, Drucker, Fernsehen, Waschmaschine, Prozessautomatisierung, Bankensoftware) • JVM (Java Virtual Machine) kann Betriebssystem für alle Computer sein. Ist etwa 200 KByte groß. • Funktionalität und Interaktivität für WWW • Software muss nicht mehr gespeichert werden, sondern kann übers Netz auf aktuellem Stand geholt werden. 29 • • • • • • einfach objekt-orientiert verteilt interpretiert robust sicher Merkmale von Java • • • • • architekturunabhängig portabel hochleistungsfähig Multithread-fähig dynamisch 30 ♣ Objektorientierte Programmierung • Identität von Objekten • Klassifizierung • Polymorphismus • Vererbung 31 ♣ Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung ♣ Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 32 Java-Programm ♣ • Klassen- und Schnittstellendefinitionen • Eigenständige Anwendung: Irgendeine Klasse muss main definieren. • public static void main (String[] arg) • arg[0] ist wirklich erstes Argument, nicht Klassenname. • Kein Rückgabewert. Workaround: System.exit (intRueckgabeWert) 33 Argumente von main public class GutenTagArg { public static void main (String[] argument) { System.out.println ("Guten Tag!"); for (int i = 0; i < argument.length; i++) { System.out.print ("Argument "); System.out.print (i); System.out.print (" war: "); System.out.println (argument[i]); } System.out.println (); } } 34 Umgebungsvariable String heimVerzeichnis = System.getProperty ("user.home"); Weitere Umgebungsvariable sind z.B.: user.name user.dir java.version java.home java.class.version os.name 35 ♣ Namensraum • Weltweit eindeutige Namen. • Keine globalen Variablen oder Methoden. • Variable und Methoden sind Klassenelemente. • Klassen gehören zu Paketen. • Paketnamen leiten sich vom Verzeichnis ab, sind damit an den Ort gekoppelt und dadurch automatisch eindeutig. 36 ♣ Namensraum PaketName.KlassenName.variablenName PaketName.KlassenName.methodenName () Beispiel: //ba-stuttgart.de/kfg/lang/java/GutenTagArg.class Paketname : de.ba-stuttgart.kfg.lang.java Klassenname : GutenTagArg Methodenname : main 37 ♣ Quellcode-Datei .java ♣ • Quellcode-Datei hat Erweiterung .java . • Kann mehrere Klassen enthalten. • Nur eine Klasse darf public sein. • Quellcode-Dateiname = Name dieser Klasse + .java 38 CLASSPATH Unix: setenv CLASSPATH .:/home/kfg/jvKlassen:/usr/local/jvKlassen Windows: SET CLASSPATH=.;a:\kfg\jvKlassen;c:\lokal\jvKlassen 39 Statement package ♣ • package lang.java.konten; • Erstes Statement nach Kommentaren. • Datei muss in dem entsprechenden Verzeichnis liegen. • Wenn Statement fehlt, dann Default-Paket. 40 Statement import • Spart Schreibarbeit. Abgekürzte Namen. • Nichts wird ”eingelesen”. • Erscheinen nach dem optionalen package-Statement. 41 ♣ Statement import 1. import Pa.cka.ge.name; 2. import Pa.cka.ge.name.Klasse; 3. import Pa.cka.ge.name.*; 42 global public Sichtbarkeit – Scope Paket default Klasse private Subklasse protected 43 Lokale Variable • Werden innerhalb von Blöcken definiert und • sind nur dort bekannt. • Argumente von Methoden sind lokal. 44 ♣ Konstanten public class Mathematik { public static final double EULER = 2.7182; public final double FAKTOR; } 45 Unicode • 16-Bit Zeichen • Zeichen, Strings, Identifikatoren • 0x0000 bis 0x00FF ist gleich ISO8859-1 • Escape-Sequenzen \uxxxx, \xxx, \n, \t usw • Beispiel: "\"" lautet alternativ "\\u0022" . 46 ♣ Standarddatentypen Typ boolean char byte short int enthält Bool’scher Wert Unicode-Zeichen ganze Zahl ganze Zahl ganze Zahl Default Bit false 1 \u0 16 0 8 0 16 0 32 long ganze Zahl 0 float IEEE-754 Zahl 0.0 double IEEE-754 Zahl 0.0 ♣ Bereich true oder false \u0000 bis \uFFFF -128 bis 127 -32768 bis 32767 -2147483648 bis 2147483647 64 -9223372036854775808 bis 9223372036854775807 32 ±3.40282347E+38 bis ±1.40239846E-45 64 ±1.797693134862231570E+308 ±4.94065645841246544E-324 47 Standarddatentypen ♣ • boolean-Werte können nicht von oder in einen anderen Typ gewandelt werden. • Werte vom Typ char haben kein Vorzeichen. • Konstanten vom Typ long: 387L oder 387l • float und double Gleitkommazahlen: 1.4F, 1.4f, 3.9D, 3.9d 48 Standarddatentypen ♣ • In den Klassen java.lang.Float und java.lang.Double sind die Konstanten POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN (not a number), MAX_VALUE (größter Absolutwert), MIN_VALUE (kleinster Absolutwert) definiert. • Ganzzahlige Division durch Null wirft eine ArithmeticException. Gleitkommadivision durch Null: POSITIVE_INFINITY oder NEGATIVE_INFINITY. • Schnittstelle java.util.Enumeration. 49 Referenzdatentypen • Objekte (object) • Felder (array) 50 Referenzdatentypen • In Java gibt es keine Zeiger, (bzw alle Referenzdatentypen sind eigentlich Zeiger.) • Es gibt keine ”Adresse-von”- oder Dereferenzierungs-Operatoren. • Ein Objekt wird mit new erzeugt. • Zwei Referenzdatentypen können auf dasselbe Objekt zeigen. • Es gibt keine Zeigerarithmetik, keine Berechnung von Objektgrößen, keine Manipulation von Speicheradressen. • Defaultwert ist null. 51 Zuweisung a = b; a zeigt jetzt auf dasselbe Objekt wie b. a ist keine Kopie von b. Kopie: a = b.clone (); 52 Vergleichbare Klasse public class Zei implements Cloneable { public char c; public Zei (char c) { this.c = c; } public boolean equals (Object z) { return c == ( (Zei)z).c; } 53 Kopierbare Klasse public class Zei implements Cloneable { public Object clone () { Object kopie = null; try { kopie = super.clone (); } catch (CloneNotSupportedException e) { e.printStackTrace (); } return kopie; } } 54 Vergleich a == b; Prüft, ob a auf dasselbe Objekt wie b zeigt. Gleichheit von Objekten wird geprüft mit: a.equals (b); 55 Erzeugung von Objekten Zei c; c = new Zei (’X’); Zei String String String d = new Zei (’Y’); s = new String ("Guten Tag!"); t = "Guten Tag!"; r = "Guten Tag!"; 56 byte[] Felder f1 = new byte[20]; Zei[] f2 = new Zei[20]; int[] f3 = {27, 47, 67, 114}; String[] s = {"Gu", "ten", " ", "Tag"}; Klasse[] f = {new Klasse (...), new Klasse (...), new SubKlasse (...), ... }; int[] f4 = new int[] {27, 47, 56, 67} 57 short[][] long[][][][] long[][][][] long[][][][] long[][][][] Mehrdimensionale Felder m1 = new short[47][114]; m2 m3 m4 m5 = = = = new new new new long[36][][][]; long[36][12][][]; long[36][][12][]; // Fehler long[][17][12][]; // Fehler 58 verschiedene Zeilenlängen int[][] dreieck = new int[17][]; for (int i = 0; i < dreieck.length; i++) { dreieck[i] = new int[i + 1]; } 59 Verschachtelte Initialisierung int[][] m6 = { {5, 2}, {7, 9, 1, 6, 7}, {5, 3, 9} }; 60 Boxing und Unboxing Integer ib = 5; // box int i = ib; // unbox ib++; // unbox, increment, box Integer jb = ib + 7; // unbox ib, calculate, box result int jb List<Integer> n = new ArrayList<Integer> (); n.add (47); // box int i = n.get (0); // unbox 61 Modifikatoren • final : Kann auf Klassen, Methoden und Variable angewendet werden. • native : Kann auf Methoden angewendet werden. • synchronized : Kann auf Klassen- und Instanzmethoden angewendet werden. • transient : Kann auf Variable angewendet werden, die nicht zum dauerhaften (persistent) Zustand eines Objekts gehören. • volatile : Kann auf Variable angewendet werden und bedeutet, dass die Variable ihren Wert asynchron ändern kann. 62 Modifikatoren • volatile : Kann auf Datenelemente angewendet werden und bedeutet, dass das Datenelement seinen Wert asynchron ändern kann. • transient : Kann auf Datenelemente angewendet werden, die nicht zum dauerhaften (persistent) Zustand eines Objekts gehören. Transiente Felder werden nicht mit dem Objekt serialisiert. 63 Typen-Literale Class intTyp = int.class Class intFeldTyp = int[].class Class zeiTyp = Zei.class Class intTyp = Integer.TYPE 64 Zeichenketten • Klasse java.lang.String • nicht \0-terminiert • Konkatenierung mit Operator ”+” • ”Hallo” ist String-Objekt • String-Objekte sind nicht veränderbar. Dafür gibt es die Klasse StringBuffer. 65 Methoden von String int length () char charAt (int i) boolean equals (Object s2) int compareTo (String s2) String substring (int von) String substring (int von, int bis) String replace (char alt, char neu) 66 String Pool String t = new String t == "irgendetwas" ergibt String s = new String s == "irgendetwas" ergibt t = t.intern (); t == "irgendetwas" ergibt ("irgendetwas"); false. ("irgendetwas").intern (); true. nun auch true. 67 Methoden von java.util.ArrayList public public public public public public ArrayList (); int size (); void add (Object ob); Object get (int i); Object remove (int i); Object[] toArray (); 68 Methoden von java.util.ArrayList<T> public public public public public public ArrayList<T> (); int size (); void add (T t); T get (int i); T remove (int i); T[] toArray (T[] at); 69 Methoden von java.util.ArrayList public public public public public public ArrayList (); int size (); void add (Object ob); Object get (int i); Object remove (int i); Object[] toArray (Object[] ob); 70 Methoden von java.util.Vector public public public public public public public public Vector (); int size (); synchronized void add (Object ob); synchronized Object get (int i); synchronized boolean remove (Object ob); synchronized Object remove (int i); synchronized Enumeration elements (); synchronized int copyInto (Object[] ob); 71 import Feld als Liste java.util.*; public class FeldAlsListe { public static void main (String[] argument) { // Definition eines Feldes: String[] a = new String[] { "A", "B" }; // Verwandlung des Feldes in eine Liste: List b = new ArrayList (Arrays.asList (a)); 72 Feld als Liste // Manipulation der Liste: b.add ("C"); // Rückverwandlung der Liste in ein Feld: a = (String[]) b.toArray (new String[0]); // Ausdruck des Feldes: for (int i = 0; i < a.length; i++) { System.out.print (a[i] + " "); } System.out.println (); } } 73 import Aufzählungstyp enum java.util.*; public class EnumDemo { enum Wochentag {Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag}; public static void main (String[] arg) { ArrayList<Wochentag> wtliste = new ArrayList<Wochentag> (); wtliste.add (Wochentag.Montag); wtliste.add (Wochentag.Mittwoch); wtliste.add (Wochentag.Freitag); wtliste.add (Wochentag.Sonntag); 74 Aufzählungstyp enum System.out.println ("Wir arbeiten nur an den Tagen:"); for (Wochentag wt : wtliste) { System.out.println ("\t" + wt); } System.out.println (); 75 Aufzählungstyp enum System.out.println ("Als Argumente wurden gelesen:"); Wochentag next; for (String s : arg) { next = null; try { next = Wochentag.valueOf (Wochentag.class, s); } catch (Exception e) { e.printStackTrace (); } System.out.println ("Gelesener String: \"" + s + "\" Wochentag: " + next); } 76 int i = 0; do { next = wtliste.get (i); switch (next) { case Montag: case Dienstag: case Mittwoch: case Donnerstag: case Freitag: System.out.println (next + " ist ein Arbeitstag."); break; case Samstag: System.out.println ("Am " + next + " wird nur manchm break; case Sonntag: System.out.println ("Am " + next + " wird ganz selte break; } i++; } while (next != Wochentag.Sonntag); 77 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 78 Überladung von Operatoren ? Die Überladung von Operatoren ist in Java nicht möglich. Ausnahme: Der binäre Operator ”+” ist auch für Objekte der Klasse String definiert und bedeutet dort Konkatenierung. 79 Unäre Operatoren Unäre Operatoren wirken auf ein Datenelement. Sie sind rechts-assoziativ, d.h. -++a wird als -(++a) nicht als ++(-a) interpretiert. 80 Binäre Operatoren Die binären Operatoren verknüpfen zwei Datenelemente und sind alle – mit Ausnahme der Zuweisungsoperatoren – links-assoziativ. 81 Binäre Operatoren a + b + c + d bedeutet ((a + b) + c) + d . Aber a = b = c = d = 1 bedeutet a = (b = (c = (d = 1))) . a *= b += c = d -= 1 bedeutet a *= (b += (c = (d -= 1))) . 82 Ternärer Operator x ? y : z 83 Reihenfolge der Auswertung ist unbestimmt. int a = 0; (a *= 2) == ++a; Nur ”&&” und ”||” garantieren, dass der linke Ausdruck zuerst ausgewertet wird. 84 Keine Operatoren sind • Subskript (”[]”) • Funktionsaufruf (”()”) • new • Namensauflösung (”.”) • Kommaoperator außer in for-Schleife • sizeof gibt es nicht. 85 Division und Modulo • Division ”/” wird bei ganzzahligen Größen ganzzahlig durchgeführt. • 11 mod 3 wird dargestellt als 11 % 3 86 Bitweises Verschieben • a << b • a >> b • a >>> b 87 Logische Operatoren • Bei den logischen Operatoren ”&” und ”|” werden immer beide Seiten ausgewertet. • Bei den logischen Operatoren ”&&” und ”||” wird eventuell nur die linke Seite ausgewertet. 88 Typvergleich Ausdruck instanceof Typ 89 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 90 Anweisungen • Einfachste Anweisung: ”;” • ”a = b + c;” • Block: ”{ }” { int b = 0; a = b + c; b++; } 91 Bedingte Anweisung if (a > 0) { b = c / a; c++; } else { System.out.println ("a nicht positiv!"); b = 0; } 92 Fallunterscheidung char c; // --switch (c) { case ’a’: x = xa; break; case ’b’: case ’c’: x = xb; break; default: x = 0; break; } 93 while-Schleife a = 10; while (a > 0) { b = c / a; a--; } 94 do-while-Schleife a = 10; do { b = c / a; a--; } while (a > 0); 95 for-Schleife for (int i = 0; i < 10; i++) { a[i] = i; b[i] = i * i; } 96 Enhanced for-Loop for (Klasse x :k) { x.methode (); } 97 Sprünge • Es gibt kein Goto, aber goto ist reserviert. • break • break Sprungmarke • continue • continue Sprungmarke 98 Sprünge int a = 0; hierher: for (int i = 0; i < 10; i++) { a++; for (int j = 0; j < 20; j++) { a++; if (a == 5) continue; if (a == 6) break; if (a == 7) continue hierher; if (a == 8) break hierher; a++; } a++; } 99 Wertrückgabe Mit der return Anweisung wird die Kontrolle wieder an die aufrufende Methode zurückgegeben, wobei ein Ausdruck des Resultattyps der aufgerufenen Methode zurückzugeben ist. 100 Methodendefinition Modifikatoren Rückgabetyp Methodenname (Kommaliste von Argumenten) { Implementation } 101 Methodendefinition public double methode (int a, double x, char z) { double y; y = a * (z - ’0’); return x * y; } 102 Argumente variabler Länge public static int min (int a, int... b) { int min = a; for (int i : b) { if (i < min) min = i; } return min; 103 min min min min Argumente variabler Länge (5) (7, 4) (7, 4, 12, 3, 6) (7, new int[] {4, 12, 3, 6}) 104 Argumente variabler Länge public static int min (int a, int[] b) public void methode (Object... o) 105 Zusicherungen assert assertion; oder assert assertion : errorcode; java -ea:Klasse Klasse AssertionError 106 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung ♣ Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 107 Klassenmerkmale • Bildung neuer Typen, die den Bedürfnissen der ProgrammierIn Daten zu repräsentieren genügen. • Kontrolle des Zugangs zu Daten: Datenstrukturen können vor dem direkten Zugriff des Benutzers geschützt werden (Datenabstraktion, Datenkapselung, information hiding). • Initialisierung und Aufgabe von Objekten kann für den Benutzer transparent erfolgen. • Vermeidung von Code-Wiederholungen durch Vererbungsmechanismen. • Bildung von typunabhängigen Datenstrukturen. 108 Klassendefinition public class Klassenname // Klassenkopf, // class head { } // Klassenkörper, // class body Konvention: Klassenname beginnt mit Großbuchstaben. 109 Datenabstraktion private Daten public Elementfunktionen, Methoden public Zugriffsfunktionen oder weitere Möglichkeiten mit: protected und default 110 Klasse Klausurnote public class Klausurnote { private String fach; private char[] note = new char[3]; public public public public public } void setFach (String int setNote (String String getNumerisch String getVerbal () void drucke () { } 111 Fach) { } Note) { } () { } { } Klasse HauptKlausurnote public class HauptKlausurnote { public static void main (String[] argument) { Klausurnote bio = new Klausurnote (); bio.setFach ("Biologie"); bio.setNote ("2,3"); bio.drucke (); } } 112 setFach public void setFach (String Fach) { fach = Fach; } 113 setNote public int setNote (String Note) { int n = Note.length (); if ((n > 3) || (n == 0) || (n > 1 && Note.charAt (1) != ’,’) ) { System.out.print ("Note \"" + Note); System.out.println ("\" ist keine gültige Note!"); return -1; } 114 setNote switch (Note.charAt (0)) { case ’5’: if (n == 3 && Note.charAt (2) != ’0’) { /* Fehlermeldung */ return -1; } case ’4’: case ’3’: case ’2’: case ’1’: note[0] = Note.charAt (0); note[1] = ’,’; 115 setNote if (n < 3) note[2] = ’0’; else if (Note.charAt (2) >= ’0’ && Note.charAt (2) <= ’9’) note[2] = Note.charAt (2); else { System.out.print ("Note \"" + Note); System.out.println ("\" ist keine gültige Note!"); return -1; } return 0; default: // Fehlermeldung return -1; } } 116 getNumerisch public String getNumerisch () { return new String (note); } 117 getVerbal public String getVerbal () { double x = zahl (); if (x < 0.99) return "ungültig"; else if ( x < 1.51) return "sehr gut"; else if ( x < 2.51) return "gut"; else if ( x < 3.51) return "befriedigend"; else if ( x < 4.01) return "ausreichend"; else return "nicht ausreichend"; } 118 drucke public void drucke () { System.out.print ("Die Note "); System.out.print (fach); System.out.print (" ist "); System.out.print (getVerbal ()); System.out.print (" ("); System.out.print (getNumerisch ()); System.out.println (")."); } 119 private Elemente private double zahl () { double x = note[0] - ’0’; x = x + (note[2] - ’0’) / 10.0; return x; } } 120 this Mit der Variablen this wird immer das gerade vorliegende Objekt referenziert. this.note[1] Klärung von Namenskonflikten. Falls Methodenresultat vorliegendes Objekt ist, return this; 121 Konstruktor • Wird ein einziges Mal beim Erzeugen eines Objekts mit new aufgerufen. • Eine Klasse kann mehrere Konstruktoren haben. • Hat den gleichen Namen wie die Klasse. • Hat keinen Rückgabewert; erzeugt Objekt. 122 Konstruktoren public class Klassenname { public Klassenname (int i, int j) {} public Klassenname (double x) {} public Klassenname () {} } 123 Beispiel Klausurnote public Klausurnote (String Note, String Fach) { if (setNote (Note) == -1) { note[0] = ’0’; note[1] = ’,’; note[2] = ’0’; } setFach (Fach); } public Klausurnote (String Note) { this (Note, "N.N."); } public Klausurnote () { this (""); } 124 this () • Mit dem Schlüsselwort this () werden andere Konstruktoren derselben Klasse aufgerufen. • Der Konstruktoraufruf this () kann nur in Konstruktoren erfolgen und muss dort als erstes Statement erscheinen. 125 Anwendung von Konstruktoren public class HauptKlausurnote { public static void main (String[] argument) { Klausurnote bio = new Klausurnote (); bio.setFach ("Biologie"); bio.setNote ("2,3"); Klausurnote phy = new Klausurnote ("1,8"); Klausurnote che = new Klausurnote ("3,1", "Chemie"); } } 126 Default-Konstruktor Ein Konstruktor ohne Argumente heißt Default-Konstruktor. Der Default-Konstruktor wird vom Compiler nur dann automatisch erzeugt, wenn es keine vom KlassenImplementor definierte Konstruktoren gibt. 127 Instanz-Initialisatoren sind namenlose Code-Blöcke, die an beliebiger Stelle in der Klasse auftreten können. Sie werden in der Reihenfolge ihres Auftretens nach dem Superklassen-Konstruktor, aber vor allen anderen Konstruktoren abgearbeitet. Damit kann man z.B. Objektfelder an der Stelle ihres Auftretens initialisieren, was die Lesbarkeit des Codes erhöhen kann, und anonyme Klassen initialsisieren. 128 Aufgabe von Objekten • ist nicht Sache des Programmierers. garbage collection, GC • Empfehlung an GC möglich: int[] riesig = new int[1000000]; // benutzt riesig // riesig wird nicht mehr benötigt riesig = null; • Vor Deallokierung wird finalize aufgerufen. • System.gc (); 129 Destruktor-Methode finalize • Der Java-Interpreter kann verlassen werden, ohne dass der Garbage-Kollektor die Möglichkeit hat, alle Objekte zu deallokieren. • Es ist nicht spezifiziert, wann und in welcher Reihenfolge der Garbage-Kollektor die Objekte deallokiert. • Eine finalize-Methode kann das Objekt wieder zum Leben erwecken, indem this wieder einer Variablen zugewiesen wird. In solch einem Fall wird finalize nicht wieder aufgerufen, wenn das Objekt schließlich deallokiert werden kann. • finalize-Methoden können Exceptions werfen. Wenn diese Exceptions nicht gefangen werden, werden sie ignoriert. 130 Beispiel finalize protected void finalize () throws Throwable { System.out.print ("Die Note "); System.out.print (fach); System.out.print (" ("); System.out.print (getVerbal ()); System.out.print (" ("); System.out.print (getNumerisch ()); System.out.println (")) wird gleich deallokiert."); super.finalize (); } 131 Die Aktivität des GC kann man mit der Option -verbosegc beobachten: public class Speicherfresser { public static void main (String[] arg) { int i = 0; while (true) { i++; System.err.println ("Iteration " + i); double[] d = new double[10000]; for (int j = 0; j < d.length; j++) d[j] = Math.random (); } } } 132 Klassenvariable und -methoden • Werden static deklariert. • Klassenvariable sind Datenelemente, auf die alle Instanzen der Klasse zugreifen können. • Klassenvariable und -methoden können ohne Instanz angesprochen werden, nur mit dem Klassennamen. • Möglichkeit zur Emulation von ”globalen” Variablen. 133 Beispiel Klassenvariable public class Klausurnote { // --static int anzKlausurnoten = 0; // --} 134 Verwendung von Klassenvariablen Klausurnote a = new Klausurnote (); a.anzKlausurnoten = 5; Klausurnote.anzKlausurnoten = 6; 135 Klassenmethoden public class Klausurnote { // --public Klausurnote besser (Klausurnote b) { if (zahl () < b.zahl ()) return this; else return b; } public static Klausurnote besser (Klausurnote a, Klausurnote b) { if (a.zahl () < b.zahl ()) return a; else return b; } // --} 136 static-Initialisator public class Klausurnote { // --static int[] feld; static { feld = new int[20]; for (int i = 0; i < 20; i++) { feld[i] = i; } } // --} 137 static-Initialisator • Beliebig viele Initialisatoren sind möglich. • native Methoden werden typischerweise mit System.load oder System.loadLibrary in einem Initialisator geladen. • static Methoden können von Erben nicht überschrieben werden. 138 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 139 Vererbung ”Ist-ein”oder ErweiterungsSubstitutions-Beziehung Angestellter ist eine Person Dampflokomotive ist eine Lokomotive Lokomotive ist ein Fahrzeug Girokonto ist ein Konto Quadrat ist ein Rechteck? 140 oder Vererbung • Erweiterung oder Spezialisierung: Erzeugung neuer Typen durch Anfügen von zusätzlichen Eigenschaften an alte Typen (Angestellter – Person) • Reduktion auf Gemeinsamkeiten oder Generalisierung: Definition einer gemeinsamen Schnittstelle für verschiedene Typen 141 Syntax des Vererbungsmechanismus public class B extends A { // --} A heißt Basisklasse, Obertyp oder Superklasse, von der B abgeleitet wird oder von der B erbt. B heißt Untertyp oder Subklasse. 142 Graphische Darstellung A A B B C 143 Mehrfachvererbung nicht möglich! A B C D Aber beliebig viele Schnittstellen können geerbt werden. 144 final Klassen Von einer als final deklarierten Klasse kann nicht geerbt werden. z.B. String, Integer, Double usw. 145 Klasse Object Object ist Basisklasse aller Klassen (außer von Object). Die Methoden, die in Object definiert sind, können von jedem Java-Objekt aufgerufen werden. 146 Methoden von Object public final Class getClass (); public String toString (); public boolean equals (Object obj); protected native Object clone () throws CloneNotSupportedException; protected void finalize () throws Throwable; 147 Polymorphismus Jedes Objekt einer abgeleiteten Klasse ist auch ein Objekt der Basisklasse. class B extends A {} // --B A b = new B (); a = b; 148 Beispiel Polymorhismus class A { void f (String s) { System.out.println (s + ": f kommt von A."); } } class B extends A { void f (String s) { System.out.println (s + ": f kommt von B."); } void g (String s) { System.out.println (s + ": g kommt von B."); } } 149 Beispiel Polymorphismus public class Polymorphismus { public static void main (String[] argument) { A a = new A (); B b = new B (); a.f ("a.f ()"); a = b; a.f ("a.f ()"); // a.g ("a.g ()"); // Fehler b.g ("b.g ()"); } } 150 mehr zur Syntax • ”überschreiben” und ”überladen” • Eine final-deklarierte Methode kann in einer abgeleiteten Klasse nicht überschrieben werden. • Alle static und alle private Methoden – wie auch alle Methoden einer final Klasse – sind implizit final. • Überschreibende Methode kann höhere Sichtbarkeit haben. 151 Referenz hat • statischen Typ: Wird bei Deklaration festgelegt. • dynamischen Typ: Wird durch das referenzierte Objekt bestimmt. dynamic method lookup 152 Überschreiben von Variablen class A { int z = 1; void f () {}} class B extends A { int z = 2; void f () {}} class C extends B { int z = 3; void f () {} public void zugriff () { 153 Überschreiben von Variablen z = 5; f (); this.z = 5; this.f (); ((B) this).z = 5; super.z = 5; ((B) this).f (); super.f (); ((A) this).z = 5; super.super.z = 5; ((A) this).f (); super.super.f (); } // // // // // // // // // // // // z von C f von C z von C f von C z von B z von B f von C f von B z von A Fehler f von C Fehler } 154 Konstruktoren class A { private int a; public A (int k) { a = k; } } class B extends A { public B () { super (17); // --} } 155 finalize protected void finalize () throws Throwable { // --super.finalize (); } 156 Reihenfolge der Initialisierung 1. Speicher für Datenelemente aller Klassen einer Vererbungshierarchie und Initialisierung mit Defaultwerten 2. Für jede Klasse einer Vererbungshierarchie (beginnend mit der obersten Basisklasse) (a) Instanzinitialisatoren (b) Konstruktor(en) Bemerkung: Polymorphes Verhalten der Methoden in Initialisatoren und Konstruktoren. 157 Abstrakte Klassen • Durch den Modifikator abstract wird eine Klasse abstrakt. public abstract class AbtrakteKlasse {} Von einer abstrakten Klasse können keine Objekte angelegt werden. • Durch den Modifikator abstract wird eine Methode abstrakt. Eine abtrakte Methode hat anstatt einer Implementation ein Semikolon. public abstract void methode (); Eine Klasse mit einer abtrakten Methode ist automatisch abstrakt und muss auch so deklariert werden. 158 Beispiel ZweiDimGebilde public abstract class ZweiDimGebilde { public String name; public ZweiDimGebilde (String name) { this.name = name; } public abstract double flaeche (); public abstract double umfang (); public static void main (String[] argument) { } } 159 Beispiel ZweiDimGebilde public abstract class ZweiDimGebilde { public static void main (String[] argument) { ZweiDimGebilde[] zdg = new ZweiDimGebilde[2]; zdg[0] = new Kreis ("Rundes", 12.0); zdg[1] = new Rechteck ("Eckiges", 17.0, 9.5); for (int i = 0; i < zdg.length; i++) { System.out.print (zdg[i].name + " : "); System.out.print ("Fläche = "); System.out.print (zdg[i].flaeche ()); System.out.print (" Umfang = "); System.out.println (zdg[i].umfang ()); } } 160 Beispiel ZweiDimGebilde class Kreis extends ZweiDimGebilde { private double radius; public Kreis (String name, double radius) { super (name); this.radius = radius; } public double flaeche () { return java.lang.Math.PI * radius * radius; } public double umfang () { return 2 * java.lang.Math.PI * radius; } } 161 Beispiel ZweiDimGebilde class Rechteck extends ZweiDimGebilde { private double laenge; private double breite; public Rechteck (String name, double x, double y) { super (name); if (x > y) { laenge = x; breite = y; } else { laenge = y; breite = x; } } public double public double } flaeche () { return laenge * breite; } umfang () { return 2 * laenge + 2 * breite; } 162 Schnittstelle – interface public interface DarstGebilde { void zeige (); } Alle Methoden einer Schnittstelle sind implizit abstract und public. Nur Klassenkonstanten sind definierbar (static final). 163 Schnittstelle – interface <<interface>> Schnittstelle Klasse 164 Beispiel DarstGebildeMain public class DarstGebildeMain { public static void main (String[] argument) { DarstGebilde[] zdg = new DarstGebilde[2]; zdg[0] = new DarstKreis ("Rundes", 12.0); zdg[1] = new DarstRechteck ("Eckiges", 17.0, 9.5); for (int i = 0; i < zdg.length; i++) { zdg[i].zeige (); } } } 165 Beispiel DarstGebildeMain class DarstKreis extends Kreis implements DarstGebilde { public DarstKreis (String name, double radius) { super (name, radius); } public void zeige () { System.out.print ("Kreis " + name + " : "); System.out.print ("Fläche = "); System.out.print (flaeche ()); System.out.print (" Umfang = "); System.out.println (umfang ()); } } 166 Beispiel DarstGebildeMain class DarstRechteck extends Rechteck implements DarstGebilde { public DarstRechteck (String name, double x, double y) { super (name, x, y); } public void zeige () { System.out.print ("Rechteck" + name + " : "); System.out.print ("Fläche = "); System.out.print (flaeche ()); System.out.print (" Umfang = "); System.out.println (umfang ()); } } 167 Schnittstellen • Eine Klasse, die eine Schnittstelle implementiert, muss alle Methoden der Schnittstelle implementieren. • Eine Klasse kann beliebig viele Schnittstellen implementieren. • Konstanten, die in einer Schnittstelle definiert wurden, können in der implementierenden Klasse und deren Subklassen ohne Referenz auf den Namen der Schnittstelle verwendet werden. 168 Sub-Schnittstellen public interface S1 extends S01, S02, S03 { // eigene Methoden } Bei Schnittstellen ist Mehrfachvererbung möglich! 169 Klasse java.lang.Class Bietet Informationen über Klassen. Class c = Class.forName ("Klausurnote"); // oder: Class c = Klausurnote.class; Klausurnote k = (Klausurnote)c.newInstance (); 170 Beispiel für Class // in main: Class c = Class.forName (argument[0]); S s = (S) c.newInstance (); s.zeige (); interface S { void zeige (); } class A implements S { public void zeige () { System.out.println ("Es grüßt Sie A!"); } } 171 Implementation von clone public class A implements Cloneable { private int intDatenElement; private String stringDatenElement; private B cloneableDatenElement; public Object { } } clone () 172 Implementation von clone public Object clone () { A kopie = null; try { kopie = (A) super.clone (); kopie.stringDatenElement = new String (stringDatenElement); kopie.cloneableDatenElement = (B) cloneableDatenElement.clone (); } catch (CloneNotSupportedException e) { e.printStackTrace (); } return kopie; } 173 ”Ist-ein”-Beziehung (is-a) B ist ein A. Alles, was für A zutrifft, trifft auch für B zu. Die Objekte von B sind eine Teilmenge der Objekte von A. Objekte von B können Objekte von A voll ersetzen (Substitutionsprinzip). class B extends A { //--} 174 ”Ist-ein”-Beziehung (is-a) • private Methoden von A sind Methoden, die nicht geerbt werden. • final Methoden von A sind Methoden, deren Schnittstelle und deren Implementation geerbt werden. Sie können nicht überschrieben werden. • abstract Methoden von A sind Methoden, deren Schnittstelle nur geerbt wird. Sie müssen implementiert werden. • Bei allen anderen Funktionen wird die Schnittstelle geerbt. Außerdem können sie neu implementiert werden. 175 Beziehung ”Ist-fast-ein” (is-like-a) Bei dieser Beziehung sollte man die Gemeinsamkeiten der Partner A und B in einer abstrakten Klasse, etwa G, zusammenfassen, von der A und B erben. 176 Beziehung ”Ist-fast-ein” (is-like-a) G A B 177 ”Hat-ein” – Beziehung (has-a) ”Ist-implementiert-mit”-Beziehung, Layering, Containment, Embedding, Einbettung, Komponente und Komponentengruppe, ”tiefe” Kopie bezüglich Komponente class A {---} class B { private A a; private A[] a = new A[10]; } 178 ”Benutzt-ein” – Beziehung (uses-a) ”flache” Kopie bezüglich Benutztem class A {---} class B { private A } a; 179 Andere Beziehungen • Definition einer eigenen Klasse für die Beziehung • Diese Klasse enthält dann die Partner der Beziehung als Datenelemente. • Zusätzlich können – aus Effizienzgründen – Objekte oder Felder von Objekten der Beziehung in den Partnerklassen verwaltet werden. 180 Botschaften In der Objektorientierung spielen Botschaften messages an Objekte von anderen Objekten eine große Rolle. In Java wird das Senden einer Botschaft an ein anderes Objekt dadurch implementiert, dass eine Methode des die Botschaft empfangenden Objekts aufgerufen wird. 181 Mehrfachvererbung Java kennt keine Mehrfachvererbung. Sie kann nur so implementiert werden, dass höchstens eine der Basisklassen geerbt wird. Für die anderen Basisklassen müssen Schnittstellen definiert werden. Die Mehrfacherbin hat von diesen nicht geerbten Basisklassen je ein Datenelement und implementiert mit diesen Datenelementen die Schnittstellen, wobei zu empfehlen ist, dass die Basisklassen die entsprechenden Schnittstellen auch implementieren. 182 Beispiel Mehrfachvererbung Wasser Land - raeder :int + fahren () :void - wasserverdr :double + schwimmen () :void Amphibie 183 Beispiel Mehrfachvererbung Land - raeder :int + fahren () :void <<interface>> WasserSchnittstelle schwimmen () :void 1 Wasser Amphibie - wasserverdr :double + schwimmen () :void 184 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 185 Signale • Zeigt besondere Situation an. • Ein Signal Werfen (throw) bedeutet, das Signal zu geben. • Ein Signal Fangen (catch) bedeutet, die entsprechende Ausnahmesituation zu behandeln (handle). 186 Syntax // --try { // --throw objekt; // --} catch (Typ_des_Objekts e) { // --} catch (Typ_von_anderen_Objekten e) { // --} finally { // --} // --- 187 finally-Block 1. Normalerweise nach Abarbeitung des try-Blocks. 2. Nach Werfen einer Exception und Abarbeitung des catch-Blocks. 3. Nach Werfen einer Exception, für die es hier kein catch gibt. 4. Nach einem break, continue oder return im try-Block. • Wenn der finally-Block selbst ein throw, break, continue oder return macht, dann wird die laufende Abbruchs-Aktion abgebrochen und diese neue Abbruchs-Aktion weiterverfolgt. 188 Ausnahme-Objekte müssen von java.lang.Throwable erben. • java.lang.Error : Diese Fehler betreffen Probleme des Bindens im Zusammenhang mit dynamischem Laden von Code oder Probleme der virtuellen Maschine (Speicherplatz). • java.lang.Exception : Von diesen Fehlern kann sich ein Programm meistens erholen (z.B. java.io.EOFException oder java.lang.ArrayAccessOutOfBounds). Diese Klassen enthalten meistens eine Diagnose-Methode und Status-Methoden oder -Variablen, die im catch-Block verwendet werden können. 189 Object Throwable Error Exception anormal RuntimeException 190 void Deklaration von Exceptions methode () throws Ausnahme1, Ausnahme2 {} • Eine Methode muss Exceptions deklarieren, wenn sie nicht von ihr behandelt werden. • Nur ”normale” Exceptions müssen deklariert werden. ”Nicht-normal” sind Error und RuntimeException • Es genügt eine Superklasse zu deklarieren. • Fehler- oder Ausnahmehierarchien. 191 Basisklasse Throwable • printStackTrace () printStackTrace (PrintWriter s) • fillInStackTrace () : throw e; throw (Ausnahmetyp)(e.fillInStackTrace ()); 192 Best Practices • Arbeite mit einer möglichst spezifischen Exception. • Vermeide leere catch-Blöcke. • Javadoc kennt das @throws-Tag. • RuntimeExceptions müssen nicht deklariert und abgefangen werden. Es ist nicht Best Practice, RuntimeExceptions in einem try-catch-Block zu behandeln. Es ist besser den Fehlerfall durch geeigneten Code abzufangen. • Anstatt eigene Fehlerklassen zu schreiben sollte man versuchen, die vom JSDK zur Verfügung gestellten Klassen zu verwenden. 193 Beispiel public class Ausnahme { public static void main (String[] argument) throws A1 { // --a.f (übergebenesIntegerargument); } void f (int i) throws A1 { // abhängig von i verschiedene Abbruchaktion // Ruft evtl. auch ff (i) auf. } void ff (int i) throws A1, A2, A4 { // Ruft fff (i) auf. // Behandelt einige Fehler selbst. } void fff (int i) throws A1, A2, A3, A4, A5 { // Wirft in Abhängigkeit von i verschiedene Fehlerobjekte. // Behandelt einige davon. } } 194 Beispiel class A extends Throwable { A (String diag) { this.diag = diag; } void diagnose () { Ausnahme.bem ("Ausnahme " + diag + " wurde geworfen."); } private String diag; } class A1 extends A { A1 () { super ("A1"); } } class A2 extends A { A2 () { super ("A2"); } } class A3 extends A { A3 () { super ("A3"); } A3 (String diag) { super (diag); } } class A4 extends A { A4 () { super ("A4"); } } class A31 extends A3 { A31 () { super ("A31"); } } 195 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 196 Innere Klassen • Block-Struktur und Klassen-Struktur • Adapter-Klassen • Syntax: – als Klassenelement – im Block – anonym im Block – static innere Klasse oder Schnittstelle • Bezug auf äußeres Objekt muss klar sein. 197 Beispiel innere Klassen public class AeussereKlasse { public static void main (String[] argument) { AeussereKlasse ak = new AeussereKlasse (); ak.f (); InnereKlasse ik = ak.new InnereKlasse (); ik.f (); ak.ff (); ak.fff (); } // --} 198 Beispiel innere Klasse als Element void f () { System.out.println ("Kommt von der äußeren Klasse."); InnereKlasse k = new InnereKlasse (); k.f (); } class InnereKlasse { void f () { System.out.print ("Kommt von der inneren Klasse, "); System.out.println ("die als Element definiert ist."); } } 199 Beispiel innere Klasse im Block void ff () { class InBlockKlasse { void f () { System.out.print ("Kommt von der inneren Klasse, "); System.out.println ("die im Block definiert ist."); } } new InBlockKlasse ().f (); } 200 interface Beispiel innere Klasse anonym KlasseOderSchnittstelle { void f (); } void fff () { (new KlasseOderSchnittstelle () { public void f () { System.out.print ("Kommt von der inneren Klasse, "); System.out.println ("die im Block anonym definiert ist."); } } ).f (); } 201 Schmier mit anonymen Klassen loeschKnopf.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent event) { Graphics g = Schmier.this.getGraphics (); Rectangle r = Schmier.this.getBounds (); g.setColor (Schmier.this.getBackground ()); g.fillRect (r.x, r.y, r.width, r.height); } } ); 202 package Callable und anonyme Klassen java.util.concurrent; public interface Callable<V> { V call () throws Exception; } Beispiel Rechner.java 203 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 204 Scheduler • Prioritätsgesteuertes unterbrechendes Scheduling ohne Zeitscheiben. (priority based preemptive scheduling without time slicing) • Abgabe des Prozessors durch yield, sleep oder wait • Bei gleicher Priorität nimmt Scheduler den Thread, der am längsten gewartet hat. • Man muss aber die Gegebenheiten des zugrundeliegenden Betriebssystems beachten: evtl. doch Zeitscheiben und weniger Prioritätsstufen. 205 Erben von Thread public class MeinThread1 extends Thread { public void run () { // Eigentlicher Threadcode } } Anwendungscode: MeinThread1 p = new MeinThread1 (); p.start (); 206 Implementation von Runnable public class MeinThread2 implements Runnable { public void run () { // Eigentlicher Threadcode } } Anwendungscode: MeinThread2 ob = new MeinThread2 (); Thread p = new Thread (ob); p.start (); 207 Beispiel ErbtThread public class ErbtThread { public static void main (String[] argument) { MeinThread1 herr = new MeinThread1 ("Herr"); herr.start (); MeinThread1 knecht = new MeinThread1 ("Knecht"); knecht.start (); } } 208 Beispiel ErbtThread class MeinThread1 extends Thread { private String name; public MeinThread1 (String name) { this.name = name; } public void run () { while (true) { System.out.println ("Thread " + name + " läuft."); yield (); } } } 209 Beispiel ImpleRunnable public class ImpleRunnable { public static void main (String[] argument) { MeinThread2 herr = new MeinThread2 ("Herr"); Thread herrTh = new Thread (herr); herrTh.start (); MeinThread2 knecht = new MeinThread2 ("Knecht"); Thread knechtTh = new Thread (knecht); knechtTh.start (); } } 210 Beispiel ImpleRunnable class MeinThread2 implements Runnable { private String name; public MeinThread2 (String name) { this.name = name; } public void run () { while (true) { System.out.println ("Thread " + name + " läuft."); Thread.yield (); } } } 211 Methoden von Thread • start () startet Thread. • Thread.yield () gibt Kontrolle an anderen Thread gleicher Priorität ab. • Thread.sleep (long ms) oder Thread.sleep (long ms, int nanos) • p.join (), p.join (long ms) oder p.join (long ms, int nanos) warten, bis p zu Ende gekommen ist oder ein Timeout eintritt. • interrupt () unterbricht sleep, join und wait 212 Methoden von Thread • isAlive () • Thread.currentThread () • setName (String s), getName () 213 Threadgruppen • Jeder Thread gehört einer Threadgruppe an. • Jede Threadgruppe außer der ”Wurzel”-Threadgruppe gehört einer Threadgruppe an. • Konstruktoren: ThreadGroup (String name) ThreadGroup (ThreadGroup gruppe, String name) Thread (ThreadGroup gruppe, String name) Thread (ThreadGroup gruppe, Runnable objekt, String name) 214 GroupTree Übung: GroupTree.dumpAll () 215 Priorität public final void setPriority (int prioritaet) Je höher die Zahl, desto höher ist die Priorität. Thread.MIN_PRIORITY bis Thread.MAX_PRIORITY. Default ist Thread.NORM_PRIORITY. 216 Abbruch einer Thread? • stop () ? • suspend () ? • resume () ? 217 Synchronisation • Monitorkonzept zum Schutz von ”kritischen Bereichen”. Jedes Objekt mit kritischem Bereich bekommt zur Laufzeit einen Monitor. • Kritischer Bereich durch synchronized gekennzeichnet. • synchronized (irgendeinObjekt) { irgendeinCode } • synchronized (this) { Methodencode } • synchronized (this.getClass ()) { staticMethCode } • Lock-Implementation über Zähler. • Keine automatische Vererbung. 218 synchronized Mit synchronized werden Codestücke definiert, die atomar oder unteilbar bezüglich eines Objekts durchzuführen sind. • Modifikator einer Methode • synchronized (Ausdruck) Block • synchronized (Ausdruck.getClass ()) Block Vermeidung von Prioritätsinversion durch PrioritätsVererbung ist für JVM nicht verpflichtend. 219 Thread Parkhaus freiePlätze :int lassEinfahren () lassAusfahren () status () warte (Nachricht :String) cstr (Kapazität :int) main (arg :String[*]) Parkhaus mit Kapazität 5 erzeugen. Zehn Autos mit demselben Parkhaus starten. Auto Nummer :int cstr (Nummer :int, p :Parkhaus) run () dreimal: lassEinfahren status warte (...) lassAusfahren status warte (...) 220 Thread Parkhaus freiePlätze :int lassEinfahren () lassAusfahren () status () warte (Nachricht :String) Parkhaus (Kapazität :int) main (arg :String[*]) Parkhaus mit Kapazität 5 erzeugen. Zehn Autos mit demselben Parkhaus starten. Auto Nummer :int Auto (Nummer :int, p :Parkhaus) run () dreimal: lassEinfahren status warte (...) lassAusfahren status warte (...) 221 wait, notify und notifyAll • Methoden der Klasse Object • Aufrufbar nur in kritischen (synchronized) Bereichen eines Objekts x. • x.wait () : Thread kommt in wait-Warteschlange für x. • x.notify () : ein Thread verlässt wait-Warteschlange für x. • x.notifyAll () : alle Threads verlassen wait-Warteschlange für x. 222 andere Sichten Ressourcen-Sicht: "beantrage Lock" und "gib Lock frei" "synchronized (x) {" und "}" Ereignis-Sicht: "warte auf Event" und "sende Event" "x.wait ()" und "x.notify ()" (oder "x.notifyAll ()") 223 Erzeuger – Verbraucher public class Puffer { private boolean belegbar = true; private Object transferObjekt; public synchronized void { while (!belegbar) { wait (); } transferObjekt = x; belegbar = false; notify (); } legeAb (Object x) 224 Erzeuger – Verbraucher public synchronized Object entnehme () { while (belegbar) { wait (); } belegbar = true; notify (); return transferObjekt; } } // end class Puffer 225 Erzeuger – Verbraucher public class Erzeuger extends Thread { private Puffer puffer; public Erzeuger (Puffer puffer) { this.puffer = puffer; } public void run () { while (true) { Object x = new Position (); puffer.legeAb (x); } } } // end class Erzeuger 226 Erzeuger – Verbraucher public class Verbraucher extends Thread { private Puffer puffer; public Verbraucher (Puffer puffer) { this.puffer = puffer; } public void run () { while (true) { Object x = puffer.entnehme (); // x wird verbraucht. } } } // end class Verbraucher 227 Erzeuger – Verbraucher public class ErzeugerVerbraucher { public static void main (String[] arg) { Puffer puffer = new Puffer (); Erzeuger erzeuger = new Erzeuger (puffer); Verbraucher verbraucher = new Verbraucher (puffer); erzeuger.start (); verbraucher.start (); } } // end class ErzeugerVerbraucher 228 Erzeuger – Verbraucher public class VieleErzeugerVerbraucher { public static void main (String[] arg) { Puffer puffer = new Puffer (); for (int i = 0; i < 10; i++) { Erzeuger erzeuger = new Erzeuger (puffer); Verbraucher verbraucher = new Verbraucher (puffer); erzeuger.start (); verbraucher.start (); } } } // end class VieleErzeugerVerbraucher 229 notify – notifyAll Im Zweifelsfall sollte anstatt von notify () notifyAll () verwendet werden!!! (Aber siehe ausführliche Diskussion später.) 230 RingPuffer Erzeuger enqueue (X) groesse - 1 0 anzahl XXX tail head 231 dequeue () Verbraucher private private private private private Klasse RingPuffer Object[] f; int groesse; int anzahl = 0; int tail = 0; int head = -1; 232 Konstruktor public RingPuffer (int groesse) { this.groesse = groesse; f = new Object[groesse]; } 233 Methode enqueue (Object ob) synchronized public void enqueue (Object ob) { while (anzahl >= groesse) wait (); f[tail] = ob; anzahl = anzahl + 1; tail = tail + 1; if (tail == groesse) tail = 0; notifyAll (); } 234 Methode dequeue () synchronized public Object dequeue () { while (anzahl == 0) wait (); anzahl = anzahl - 1; head = head + 1; if (head == groesse) head = 0; notifyAll (); return f[head]; } 235 Beispiel: Emulation von Semaphoren AllgemeinerSemaphor Semaphor # zaehler :int cstr (:int) p () v () # zaehlHoch () # zaehlRunter () # zaehlHoch () # zaehlRunter () BinaererSemaphor cstr (:boolean) # zaehlHoch () # zaehlRunter () 236 Beispiel: Emulation von Semaphoren public abstract class Semaphor { public Semaphor (int zaehler) { ... } p () { ... } v () { ... } public synchronized void public synchronized void protected int zaehler; protected abstract void zaehlHoch (); protected abstract void zaehlRunter (); } 237 Beispiel: Emulation von Semaphoren public abstract class Semaphor { public Semaphor (int zaehler) { if (zaehler < 0) this.zaehler = 0; else this.zaehler = zaehler; } 238 Beispiel: Emulation von Semaphoren public synchronized void p () { while (zaehler == 0) { try { wait (); } catch (InterruptedException e) {} } zaehlRunter (); } public synchronized void v () { zaehlHoch (); notify (); } 239 Beispiel: SchweissRoboter // ArmThread public void run () { while (true) { r.uB (); r.s1.p (); r.kP (); r.s2.v (); } } | // SchweissThread | public void run () | { | while (true) | { | r.uV (); | r.s2.p (); | r.kS (); | r.s1.v (); | } | } 240 Dämonen • Läuft immer im Hintergrund. • Java-Interpreter wird verlassen, wenn alle Threads, die nicht Dämonen sind, aufgehört haben zu laufen. • setDaemon (boolean x) (vor Thread-Start) und isDaemon () • Sparsame Verwendung sei empfohlen. 241 Thread Safety Thread-Sicherheit bedeutet, dass die Datenelemente eines Objekts oder einer Klasse immer einen korrekten oder konsistenten Zustand haben aus der Sicht anderer Objekte oder Klassen, auch wenn von mehreren Threads gleichzeitig zugegriffen wird. 242 Thread Safety Was kann man tun? Drei Möglichkeiten: 1. Kritische Bereiche erhalten ein synchronized. 2. Die Datenelemente werden unveränderbar (final) gemacht (immutable objects). 3. Man benutzt einen Thread-sicheren Wrapper. 243 Kritische Bereiche synchronized ist notwendig, wenn mehrere Threads auf gemeinsame Daten (Objekte) zugreifen und mindestens ein Thread diese Daten (Objekte) verändert. Alle Methoden, die auf die Daten (Objekte) zugreifen, müssen als synchronized deklariert werden unabhängig davon, ob nur gelesen oder auch verändert wird. Methoden-Aufrufe anderer Objekte synchronized Umgebung erfolgen. 244 sollten nicht in einer Thread Safety Warum nicht alles einfach synchronized? 1. Synchronisierte Methoden-Aufrufe sind etwa 5 mal langsamer als nicht-synchronisierte Aufrufe. 2. Unnötige Synchronisationen (etwa bei Lesezugriffen) haben überflüssiges Blockieren von Threads zur Folge. 3. Immer besteht die Gefahr eines Deadlocks. 4. Ein Codestück mit mehreren synchronisierten Aufrufen ist trotzdem nicht Thread-sicher. 245 Thread Safety if (!vector.contains (element)) { vector.add (element); } 246 Thread Safety synchronized (vector) { if (!vector.contains (element)) { vector.add (element); } } 247 volatile Variable Wenn es nur darum geht, Variable für andere Threads sichtbar zu machen (und nicht um Atomizität) (sequential consistency), dann kann – als mildere Form der Synchronisation – die Variable als volatile deklariert werden. 248 final Variable Alle Datenelemente sollten final deklariert werden, es sei denn, dass sie veränderlich sein sollen. Achtung: final Referenzen! 249 Entwurfs-Regeln Wenn durch einen Methodenaufruf der Zustand eines Objekts verändert wird und diese Änderung nur erfolgen darf, wenn eine gewisse Wartebedingung nicht mehr vorliegt, dann hat diese Methode folgende Form: synchronized void methode () { while (Wartebedingung) { wait (); } // Mach Zustandsänderung. } 250 Entwurfs-Regeln Wenn eine Zustandsänderung dazu führt, dass eventuell wartende Threads weiterlaufen können, muss ein notify oder allgemeiner ein notifyAll gegeben werden: synchronized void methode () { // Mach Zustandsänderung. notifyAll (); } 251 Entwurfs-Regeln synchronized void methode () { while (Wartebedingung) { wait (); } // Mach Zustandsänderung. notifyAll (); } 252 Entwurfs-Regeln Nach rein lesenden Zugriffen muss grundsätzlich kein Thread geweckt werden (also kein notify oder notifyAll). 253 Spurious Wakeup 254 Timeout Timeout ”0” bedeutet ”kein Timeout”, also unendlich langes Warten. Timeout-Flag. 255 Zusammenfassung wait, notify, notifyAll 1. wait, notify, notifyAll in Sync 2. while (Wartebedingung) wait (); 3. Sync muss notify oder notifyAll haben, wenn es mindestens ein wait gibt und wenn das Sync die Wartebedingung eines waits möglicherweise false macht. 4. Ein notify genügt, wenn die Anwendung so ist, dass höchstens ein Thread die wait-Warteschlange verlassen soll. 5. In allen anderen Fällen: notifyAll 256 notify oder interrupt ? x.notify () gibt irgendeinen Thread aus der wait-Warteschlange für x frei. t.interrupt () gibt genau den Thread t aus einer wait-Warteschlange frei. x.notify () kann nur in einer bezüglich x synchronized Umgebung aufgerufen werden. Abgesehen davon, dass man einen Monitor-Kontext braucht, ist notify performanter als interrupt, da keine Exception geworfen wird. notify ”verpufft” wirkungslos, wenn sich kein Thread in der waitWarteschlange befindet. interrupt ”verpufft” nicht. t.interrupt weckt einen Thread t auch aus einem sleep oder join. Bei t.interrupt wird eine InterruptedException geworfen. 257 Verklemmungen Vorranggraph: T1 T2 T5 T3 T4 T6 258 Verklemmungen: Strategien • Voranforderungsstrategie • Anforderung nach einer vorgegebenen Reihenfolge • Anforderung von Betriebsmitteln mit Bedarfsanalyse 259 Verklemmung von Zügen 260 Entwurfs-Regeln: Priorität Faustregeln: • Prio (kleine Prozesszeit) > Prio (große Prozesszeit) • Prio (I/O-intensiv) > Prio (rechen-intensiv) Grundsatz: • Korrektheit unabhängig von Priorität! 261 Entwurfs-Regeln: Priorität Priorität Thread-Typ 10 Krisen-Management 7–9 interaktiv, ereignisgesteuert 4–6 I/O-abhängig 2–3 Berechnung im Hintergrund 1 wenn wirklich nichts anderes ansteht 262 Kapselung durch Komposition public class MeinThread { private Thread task; MeinThread () { task = new Thread (new MeinRunnable ()); task.start (); } private class MeinRunnable implements Runnable { public void run () { // ... } } } 263 Komposition kompakter public class MeinThread { MeinThread () { new Thread ( new Runnable () { public void run () { // ... } } ).start (); } } 264 Vorzeitige Objekt-Veröffentlichung Wenn ein Objekt innerhalb seines Konstruktors irgendwo veröffentlicht wird (z.B. durch Registrierung des Objekts oder durch Starten eines Threads, der das Objekt benutzt), dann kann es passieren, dass das Objekt benutzt wird, ehe es vollständig konstruiert ist. 265 Abhilfe: Vorzeitige Objekt-Veröffentlichung class Klasse extends Thread { protected String a; protected Klasse () { a = "SuperKlasse"; } protected Klasse publish () { start (); // Starte als Thread oder registriere irgendwo return this; } public static Klasse newInstance () { return new Klasse ().publish (); } // ... 266 Zeitliche Auflösung void Thread.sleep (long ms) void thr.join (long ms) void ob.wait (long ms) long System.currentTimeMillis () long System.nanoTime () 267 JVMPI Java Virtual Machine Profile Interface 268 Adhoc-Thread //... sequentiell //... nun adhoc-Thread: new Thread () { public void run () { //... paralleler Code } }.start (); //... ab jetzt zwei Threads 269 Thread-sichere API-Klassen Thread-sicher: java.util.Vector java.util.Hashtable Nicht Thread-sicher: java.util.ArrayList java.util.HashMap java.util.Collections.synchronizedList (List<E> x) 270 Timer, TimerTask public class Timer { public Timer (String name, boolean isDaemon); public void cancel (); // Beendet den Timer. // Eingeplante Tasks werden ausgeplant. public int purge (); // Entfernt alle ausgeplanten TimerTasks. public void schedule (TimerTask task, Date time); public void schedule (TimerTask task, Date firstTime, long period); public void schedule (TimerTask task, long delay); public void schedule (TimerTask task, long delay, long period); public void scheduleAtFixedRate (TimerTask task, Date firstTime, long period); public void scheduleAtFixedRate (TimerTask task, long delay, long period); } 271 TimerTask public abstract class TimerTask implements Runnable { public TimerTask (); public boolean cancel (); // Task wird ausgeplant. // Wenn die Task gerade läuft, // läuft sie zu Ende. public abstract void run (); public long scheduledExecutionTime (); } 272 Thread-Pools Vermeidung des Thread-Start-Overheads Begrenzung der Anzahl der Threads public interface Executor { void execute (Runnable task); } 273 Thread-Pools ThreadPoolExecutor bietet viele Möglichkeiten. Bequem: ExecutorService es = Executors.newFixedThreadPool (int anz); 274 public class Task implements Runnable { private String name; private int wartezeit; public Task (String name, int wartezeit) { this.name = name; this.wartezeit = wartezeit; } public void run () { System.out.println ("Task " + name + System.currentTimeMillis () + try { Thread.sleep (wartezeit); } catch (InterruptedException e ) System.out.println ("Task " + name + System.currentTimeMillis () + } } + " beginnt um " "."); {} + " ist fertig um " "."); 275 { public static void main (String[] arg) { ExecutorService executor = Executors.newFixedThreadPool (3); // Wir erzeugen einen Thread-Pool mit 3 Threads. int sumWartezeit = 1000; // Wir summieren alle Wartezeiten, damit wir // wissen, wann wir den executor schließen können. java.util.Random zufall = new java.util.Random (); for (int i = 0; i < 10; i++) { String name = "" + i; int wartezeit = zufall.nextInt (1000); sumWartezeit = sumWartezeit + wartezeit; Runnable task = new Task (name, wartezeit); // Tasks werden erzeugt System.out.println ("Task " + name + " mit Wartezeit " + wartezeit + " wird an den Threadpool übergeben."); executor.execute (task); // Tasks werden dem Executor übergeben. } try { Thread.sleep (sumWartezeit); executor.shutdown (); executor.awaitTermination (sumWartezeit, TimeUnit.MILLISECONDS); } catch (InterruptedException e) {} } } 276 Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task Task 0 1 2 3 4 5 6 7 8 9 0 1 2 2 3 0 4 4 5 1 6 6 7 7 8 3 9 9 5 8 mit Wartezeit 406 wird hinzugefügt. mit Wartezeit 935 wird hinzugefügt. mit Wartezeit 247 wird hinzugefügt. mit Wartezeit 993 wird hinzugefügt. mit Wartezeit 402 wird hinzugefügt. mit Wartezeit 839 wird hinzugefügt. mit Wartezeit 14 wird hinzugefügt. mit Wartezeit 131 wird hinzugefügt. mit Wartezeit 613 wird hinzugefügt. mit Wartezeit 229 wird hinzugefügt. beginnt um 1103561602040. beginnt um 1103561602040. beginnt um 1103561602040. ist fertig um 1103561602280. beginnt um 1103561602280. ist fertig um 1103561602441. beginnt um 1103561602441. ist fertig um 1103561602841. beginnt um 1103561602841. ist fertig um 1103561602971. beginnt um 1103561602971. ist fertig um 1103561602981. beginnt um 1103561602981. ist fertig um 1103561603122. beginnt um 1103561603122. ist fertig um 1103561603272. beginnt um 1103561603272. ist fertig um 1103561603502. ist fertig um 1103561603682. ist fertig um 1103561603732. 277 java.util.concurrent.Semaphore Semaphore (int permits) Semaphore (int permits, boolean fair) 278 java.util.concurrent.Semaphore void acquire () void acquire (int permits) void acquireUninterruptibly () void acquireUninterruptibly (int permits) 279 java.util.concurrent.Semaphore boolean tryAcquire () boolean tryAcquire (int permits) boolean tryAcquire (long timeout, TimeUnit unit) boolean tryAcquire (int permits, long timeout, TimeUnit unit) 280 java.util.concurrent.Semaphore void release () 281 java.util.concurrent.Semaphore Beispiel Postschalter 282 java.util.concurrent.locks.Lock Lock s = ...; s.lock (); try { // Verwendung des geschützten // Betriebsmittels } finally { s.unlock (); } 283 Lock s = ...; try { s.lockInterruptibly (); try { // Verwendung des geschützten Betriebsmittels } finally { s.unlock (); } } catch (InterruptedException e) { System.err.println ("Thread bekam interrupt."); } 284 Lock s = ...; if (s.tryLock (200, TimeUnit.MILLISECONDS)) { try { // Verwendung des geschützten Betriebsmittels } finally { s.unlock (); } } else { // Tu was anderes ... } 285 Interface Lock public Interface Lock { void lock (); void lockInterruptibly () throws InterruptedException; Condition newCondition (); boolean tryLock (); boolean tryLock (long time, TimeUnit unit); void unlock (); } 286 Lock wird realisiert von: • ReentrantLock • ReentrantReadWriteLock.ReadLock • ReentrantReadWriteLock.WriteLock 287 java.util.concurrent.locks.Lock ReadWriteLock rwl = new ReentrantReadWriteLock (); Lock Lock readLock = rwl.readLock (); writeLock = rwl.writeLock (); 288 java.util.concurrent.locks.Lock Kompatibilitäts-Matrix: readLock writeLock readLock ja nein writeLock nein nein 289 newCondition Lock s = new ... Condition c = s.newCondition (); s.lock (); try { // ... c.await (); // ... c.signal (); // ... c.signalAll (); // ... } finally { s.unlock (); } 290 CyclicBarrier CyclicBarrier (int parties) CyclicBarrier (int parties, Runnable barrierAction) 291 CyclicBarrier void await () void await (long timeout, TimeUnit unit) 292 Task 1 Task 2 Task 3 run {barrier.await ()} run {barrier.await ()} run {barrier.await ()} barrierAction Task 1 Task 2 Task 3 continue continue continue 293 CyclicBarrier Beispiel: Roboter-Achsen 294 CountDownLatch CountDownLatch (int count) void void await () await (long timeout, TimeUnit unit) void int countDown () getCount () 295 T1 T2 T3 run {await} run {await} run {await} T1 T2 T3 cont. cont. cont. T4 T5 run {countdown} run {countdown} T4 T5 cont. cont. 296 CountDownLatch Beispiel: Arbeiter und Chef 297 Exchanger<V> Exchanger<V> exch = new Exchanger<V> (); Task 1 // ... // ... V v1 = ... v1 = exch.exchange (v1); // v1 ist nun das v2 // von rechts. Task 2 | | | | | | // ... V v2 = ... // ... v2 = exch.exchange (v2); // v2 ist nun das v1 // von links. 298 Task 1 Task 2 run {v1 = exch. exchange (v1)} run {v2 = exch. exchange (v2)} v1 v2 v2 v1 Task 1 Task 2 continue continue 299 Exchanger<V> Beispiel: Tonerkassette 300 FutureTask<Result> client <<create>> :FutureTask start () get () :Result 301 FutureTask<Result> client <<create>> :FutureTask start () get () :Result 302 FutureTask<Result> public class Vorausberechnung { public Resultat berechne () { ... return aResultat; } public FutureTask<Resultat> future = new FutureTask<Resultat> ( new Callable<Resultat> () { public Resultat call () { return berechne (); } } ); 303 FutureTask<Result> public static void { Vorausberechnung main (String[] arg) vb = new Vorausberechnung (); new Thread (vb.future).start (); // ... // Tut Dinge, für die das Resultat noch nicht benötigt wird. // ... Resultat r = vb.future.get (); } } 304 Interface java.util.Queue<E> public interface Queue<E> { boolean add (E e) throws IllegalStateException; E element () throws NoSuchElementException; boolean offer (E e); E peek (); E poll (); E remove () throws NoSuchElementException; } 305 package Interface BlockingQueue<E> java.util.concurrent; public interface BlockingQueue<E> { boolean offer (E e, long time, TimeUnit unit); void put (E e); E poll (long time, TimeUnit unit); E take (); // und weitere Methoden } 306 Queues Schnittstelle BlockingQueue ArrayBlockingQueue DelayQueue LinkedBlockingQueue PriorityBlockingQueue SynchronousQueue 307 ArrayBlockingQueue<E> public ArrayBlockingQueue<E> (int capacity) public ArrayBlockingQueue<E> (int capacity, boolean fair) public void clear () 308 package Atomare Variable java.util.concurrent.atomic; AtomicInteger AtomicLong AtomicReference<V> ... 309 Atomare Variable int addAndGet (int delta) int getAndAdd (int delta) int decrementAndGet () int getAndDecrement () int incrementAndGet () int getAndIncrement () int getAndSet (int newValue) boolean compareAndSet (int expect, int update) 310 Thread-sichere Collections List<E> liste = Collections.synchronizedList ( new ArrayList<E> ()); Map<K, E> map = Collections.synchronizedMap ( new HashMap<K, E> ()); 311 Schwach Thread-sichere Collections ConcurrentHashMap Thread-sicher: get, put, containsKey, remove, putIfAbsent, replace Nicht Thread-sicher: size, isEmpty lock striping 312 Schwach Thread-sichere Collections CopyOnWriteArrayList CopyOnWriteArraySet 313 GUI-Frameworks • single-threaded: event dispatch thread Problem: responsiveness Daher schnelle Ereignisbehandlung oder Auslagerung in eigene Thread. • Multithreaded Frameworks hatten immer Probleme mit gegenseitigem Ausschluss und Deadlocks. 314 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 315 Ein- und Ausgabeströme • Abstrakte Stream-Basis-Klassen: InputStream bzw. OutputStream • Methode close () • Reziproke read- und write-Methoden 316 Klasse InputStream • int read () • int read (byte[] b) • int read (byte[] b, int von, int anz) • Alle read-Methoden warten (block), bis ihre Einleseforderung befriedigt ist oder das Ende des Stroms erreicht ist. • int available () • skip (long n) • Objekt System.in ist Standard-Eingabe. 317 Klasse OutputStream • void write (int b) Schreibt ein Byte! • void write (byte[] b) • void write (byte[] b, int von, int anz) • Alle write-Methoden warten (block) bis alles geschrieben ist. • void flush () 318 ByteArrayInputStream byte[] feld = new byte[256]; // fülle feld mit sinnvollen Daten ByteArrayInputStream s1 = new ByteArrayInputStream (feld); // oder InputStream s2 = new ByteArrayInputStream (feld, 47, 127); • reset () 319 ByteArrayOutputStream • ByteArrayOutputStream () • ByteArrayOutputStream (int groesse) • reset () • int size () Gibt Anzahl der geschriebenen Bytes. • public synchronized byte[] toByteArray () • public String toString () • public String toString (int oberesByte) 320 Datei-Ströme • FileInputStream (String dateiname) • FileInputStream (File datei) • FileInputStream (FileDescriptor fd) • FileOutputStream hat entsprechende Konstruktoren. • FileDescriptor getFD () 321 Filter-Klassen • FilterInputStream (InputStream s) • FilterOutputStream (OutputStream s) • Methoden emulieren übergebene Stream-Klassen. • Subklassen können Methoden sinnvoll überschreiben. 322 Beispiel 1. Filter, das jedes Leerzeichen durch ein ”e” ersetzt. 2. Filter, das jedes ”e” entfernt. 323 Beispiel public static void main (String[] argument) { String text = "Das Wetter ist heute besonders schön."; byte[] feld = new byte[text.length ()]; for (int i = 0; i < feld.length; i++) feld[i] = (byte)text.charAt (i); InputStream InputStream InputStream InputStream InputStream } s = new ByteArrayInputStream (feld); gibStreamAus (s); s1 = new FilterBlankZuKleinE (s); gibStreamAus (s1); s2 = new FilterEntferntKleinE (s); gibStreamAus (s2); s3 = new FilterBlankZuKleinE (s2); gibStreamAus (s3); s4 = new FilterEntferntKleinE (s1); gibStreamAus (s4); 324 Beispiel class FilterBlankZuKleinE extends FilterInputStream { public FilterBlankZuKleinE (InputStream s) { super (s); } public int read () throws IOException { int c = super.read (); if (c == ’ ’) return ’e’; else return c; } } 325 Beispiel class FilterEntferntKleinE extends FilterInputStream { public FilterEntferntKleinE (InputStream s) { super (s); } public int read () throws IOException { int c = super.read (); while (c == ’e’) c = super.read (); return c; } } 326 Resultat Beispiel Das Wetter ist heute besonders schön. DaseWettereisteheuteebesonderseschön. Das Wttr ist hut bsondrs schön. DaseWttreistehutebsondrseschön. DasWttristhutbsondrsschön. 327 public public public public Gepufferte Ströme BufferedInputStream (InputStream s); BufferedInputStream (InputStream s, int groesse); BufferedOutputStream (OutputStream s); BufferedOutputStream (OutputStream s, int groesse); • erben von den entsprechenden Filterströmen • public synchronized void mark (int leseGrenze) • public synchronized void reset () throws IOException 328 Data-Ströme • DataInputStream • DataOutputStream • implementieren Schnittstelle DataInput bzw. DataOutput • Methoden zur Ein- bzw. Ausgabe der Bit-Sequenzen (d.h. keine formatierte oder textuelle Ausgabe als Zeichenkette) von Standardtypen • Lesemethoden werfen EOFException, wenn das Dateiende erreicht ist. 329 Beispiel try { while (true) { int i = s.readInt (); // verarbeite i } } catch (EOFException e) { // Stream-Ende wurde erreicht. Da muss man nichts tun. } catch (IOException e) { // Eingabefehler ist aufgetreten. Da muss man irgendetwas machen. } 330 Pipe-Verbindung PipedInputStream ein; PipedOutputStream aus; aus = new PipedOutputStream (); ein = new PipedInputStream (); aus.connect (ein); oder PipedInputStream ein = new PipedInputStream (); PipedOutputStream aus = new PipedOutputStream (ein); oder umgekehrt. 331 Konkatenierung von Streams public SequenceInputStream (InputStream a, InputStream b); public SequenceInputStream (Enumeration e); InputStream s1, s2, s3; Vector v = new Vector (); v.addElement (s1); v.addElement (s2); v.addElement (s3); InputStream s = new SequenceInputStream (v.elements ()); 332 Klasse RandomAccessFile • implementiert DataInput und DataOutput • Konstruktoren: public RandomAccessFile (String dateiname, String modus); public RandomAccessFile (File datei, String modus); • modus kann entweder "r" oder "rw" sein. • public long length () Länge der Datei • public void seek (long pos) Positionierung des Lese- oder Schreibzeigers. 333 Klasse File Objekte der Klasse File repräsentieren Dateien oder Verzeichnisse. Es werden die typischen BetriebssystemFunktionen eines Datei-Managers als Methoden zur Verfügung gestellt. 334 Reader BufferedReader LineNumberReader CharArrayReader InputStreamReader FileReader FilterReader PushbackReader PipedReader StringReader char-Streams Writer BufferedWriter CharArrayWriter OutputStreamWriter FileWriter FilterWriter PipedWriter StringWriter PrintWriter 335 BufferedReader Eine sehr nützliche Methode von BufferedReader ist: public String readLine () throws IOException; 336 PrintStream und PrintWriter • Textuelle Ausgabe von Standard- und Referenztypen. • PrintWriter ist vorzuziehen. • print () und println () • Methode toString () wird dabei verwendet. • Objekte System.out und System.err sind PrintStreams. 337 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 338 Klasse URL • Uniform Resource Locator • URL url = new URL (urlAdresse); • urlAdresse = file:/var/home/kfg/dy.java oder urlAdresse = http://www.ba-stuttgart.de/~kfg/dy.java • (String)(url.getContent ()) • c.createImage ((ImageProducer)(url.getContent ())) • InputStream ein = url.openStream (); 339 Klasse URLconnection • URLconnection uc = url.openConnection (); • InputStream ein = uc.getInputStream (); • OutputStream aus = uc.getOutputStream (); • Ermittlung von Datei-Informationen 340 Datagramme • UDP – universal datagram protocol • Klassen DatagramPacket und DatagramSocket • Senden: InetAddress adr = InetAddress.getByName (argument[0]); DatagramPacket paket = new DatagramPacket (botschaft, botschaft.length, adr, port); DatagramSocket socket = new DatagramSocket (); socket.send (paket); 341 Datagramme • Empfangen: byte[] botschaft = new byte[256]; DatagramPacket paket = new DatagramPacket (botschaft, botschaft.length); DatagramSocket socket = new DatagramSocket (port); socket.receive (paket); 342 Client/Server • Für eine zuverlässige (TCP – reliable) Verbindung zwischen Client und Server wird die Klasse Socket verwendet. • Objekte der Klasse ServerSocket warten auf Verbindungsanforderungen und liefern im Falle einer Verbindung neue SocketObjekte zur Kommunikation mit dem Client. • Der Server ist multithreaded. • Der Client erzeugt einen Socket: Socket s = new Socket (adresse, port); InputStream ein = s.getInputStream (); OutputStream aus = s.getOutputStream (); 343 Klasse Dienst public class Dienst extends Thread { public static void main (String[] argument) { int lokalerPort = Integer.parseInt (argument[0]); new Dienst (lokalerPort); } protected ServerSocket dienstSocket; 344 Klasse Dienst public Dienst (int lokalerPort) { dienstSocket = new ServerSocket (lokalerPort); this.start (); } public void run () { while (true) { Socket kundenSocket = dienstSocket.accept (); Verbindung v = new Verbindung (kundenSocket); } } } 345 Klasse Verbindung class Verbindung extends Thread { protected Socket kundenSocket; protected BufferedReader ein; protected PrintWriter aus; public Verbindung (Socket kundenSocket) { this.kundenSocket = kundenSocket; ein = new BufferedReader (new InputStreamReader ( kundenSocket.getInputStream ())); aus = new PrintWriter (new OutputStreamWriter ( kundenSocket.getOutputStream ())); this.start (); } 346 Klasse Verbindung public void run () { String zeile; while ((zeile = ein.readLine ()) != null) { aus.print ("Natürlich "); aus.println (zeile.replace (’?’, ’.’)); aus.flush (); if (zeile.equals ("quit")) break; } } } 347 Klasse Kunde public class Kunde { public static void main (String[] argument) { int entfernterPort = Integer.parseInt (argument[1]); Socket s = new Socket (argument[0], entfernterPort); BufferedReader sein = new BufferedReader ( new InputStreamReader (s.getInputStream ())); PrintWriter saus = new PrintWriter ( new OutputStreamWriter (s.getOutputStream ())); BufferedReader eingabe = new BufferedReader ( new InputStreamReader (System.in)); 348 Klasse Kunde while (true) { System.out.println ("Eingabe der Frage:"); System.out.print ("> "); System.out.flush (); String frage = eingabe.readLine (); saus.println (frage); saus.flush (); System.out.println ("Antwort:"); String antwort = sein.readLine (); if (antwort == null) break; System.out.println (antwort); if (frage.equals ("quit")) break; } } } 349 Klasse KundeApplet public class KundeApplet extends Applet implements ActionListener { int entfernterPort = DEFAULTPORT; PrintWriter saus; BufferedReader sein; Socket s; TextField textFeld; TextArea textBereich; Empfaenger empfaenger; 350 Klasse KundeApplet public void init () { entfernterPort = Integer.parseInt ( getParameter ("Port")); s = new Socket (this.getCodeBase ().getHost (), entfernterPort); sein = new saus = new new BufferedReader ( InputStreamReader (s.getInputStream ())); new PrintWriter ( OutputStreamWriter (s.getOutputStream ())); 351 Klasse KundeApplet this.setLayout (new BorderLayout ()); Panel panel = new Panel (); Label eingabe = new Label ("Eingabe der Frage: ", Label.LEFT); panel.add (eingabe); textFeld = new TextField (40); textFeld.addActionListener (this); panel.add (textFeld); this.add ("North", panel); textBereich = new TextArea (); this.add ("Center", textBereich); empfaenger = new Empfaenger (this, sein, textBereich); } 352 Klasse KundeApplet public void actionPerformed (ActionEvent e) { if (e.getSource () == textFeld) { saus.println (e.getActionCommand ()); saus.flush (); textFeld.setText (""); } } } 353 Klasse Empfaenger class Empfaenger extends Thread { Applet applet; BufferedReader ein; TextArea aus; public Empfaenger (Applet applet, BufferedReader sein, TextArea textBereich) { this.applet = applet; ein = sein; aus = textBereich; this.start (); } 354 Klasse Empfaenger public void run () { String zeile; while ((zeile = ein.readLine ()) != null) { aus.setText (zeile); if (zeile.endsWith ("quit")) { applet.stop (); return; } } } } 355 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 356 AWT und Swing • Swing ist Teil von JFC. • Swing baut auf AWT auf. • Swing benutzt MVC-Design. • Swing ist flexibler, größer, protabler als AWT. • Swing ist schneller und weniger Speicher-intensiv als AWT. • Swing-Komponenten beginnen mit J. 357 Graphische Benutzeroberflächen • Komponenten (component) JComponent • Behälter (container) Container • Hierarchie: Behälter ist auch Komponente. • Anordnung mit Layout-Managern • Anwendungsprogramme gehen von JFrame, • Applets erben JApplet . 358 Layout-Manager von AWT • FlowLayout • GridLayout • GridBagLayout • BorderLayout • CardLayout • Setzen eines Layout-Managers mit Methode setLayout (new FlowLayout ()); 359 Layout-Manager von Swing • BoxLayout • OverlayLayout • ScrollPaneLayout • ViewportLayout 360 FlowLayout • Anordnung zeilenweise • Default zentriert • Bündigkeit: FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER • Konstruktor: FlowLayout ( Bündigkeit, Horizontal-, Vertikalabstand) 361 GridLayout • Konstruktor: GridLayout ( Zeilen, Spalten, Horizontal-, Vertikalabstand) 362 BorderLayout NORTH WEST CENTER EAST SOUTH • Konstruktor: BorderLayout (Horizontal-, Vertikalabstand) • add (new JButton ("Nord"), BorderLayout.NORTH); 363 CardLayout JPanel karten = new JPanel (); CardLayout kartenLayout = new CardLayout (); karten.setLayout (kartenLayout); JPanel karte1 = new JPanel (); String nameKarte1 = "Knöpfe"; // Fülle karte1 mit Knöpfen oder ähnlichem karten.add (nameKarte1, karte1); JPanel karte2 = new JPanel (); String nameKarte2 = "Textfelder"; // Fülle karte2 mit Textfeldern oder ähnlichem karten.add (nameKarte2, karte2); 364 CardLayout kartenLayout.first (karten); kartenLayout.next (karten); kartenLayout.previous (karten); kartenLayout.last (karten); kartenLayout.show (karten, nameKarte2); 365 GridBagLayout • Zeilen und Spalten • Komponenten können mehrere Zeilen und Spalten beanspruchen. • Zellen gewichtet • Spezifikation mit GridBagConstraints-Objekt 366 Vorgehensweise GridBagLayout JPanel sack = new JPanel (); sack.setLayout (new GridBagLayout ()); GridBagConstraints c = new GridBagConstraints (); // Für jede Komponente komponente, die zum JPanel sack addiert wird, // werden die Parameter des GridBagConstraints c gesetzt. // z.B. c.gridx = 3; c.gridy = 4; // usw sack.add (komponente, c); 367 GridBagConstraints gridx, gridy: Spezifikation der Spalten und Zeilennummer der Zelle beginnend bei 0 oder RELATIVE (bezüglich zuletzt addierter Komponente). gridwidth, gridheight: Anzahl Spalten und Zeilen, die die Zelle einnimmt. fill: Angabe der Art, wie die Komponente die Zelle ausfüllen soll (NONE (Default), HORIZONTAL, VERTICAL, BOTH). ipadx, ipady: Die Minimalgröße der Komponente wird um 2 * ipadx bzw 2 * ipady Pixel vergrößert. insets: Spezifikation des externen Padding durch Angabe eines InsetsObjekt. anchor: Spezifikation des Ortes innerhalb der Zelle (CENTER (Default), NORTH, NORTHEAST usw). weightx, weighty: Mit den Gewichten zwischen 0.0 (Default!) und 1.0 wird spezifiziert, wie übriger Platz verteilt wird. 368 Klasse Insets public class meinBehaelter extends JPanel { // ... public Insets getInsets () { return new Insets (17, 8, 20, 5); // oben, links, unten, rechts } // ... } 369 Koordinaten von Komponenten void setBounds (int x, int y, int breite, int hoehe) void setBounds (Rectangle r) void void void void setLocation (int x, int y) setLocation (Point p) setSize (int breite, int hoehe) setSize (Dimension d) Dimension getScreenSize () int getScreenResolution () Toolkit.getDefaultToolkit () 370 Java-Bean Jede Swing-Komponente ist ein Java-Bean. Z.B. Klasseneigenschaft background: background {Color, get, set, Color.black} Der Defaultwert ist Color.black und es gibt die Methoden: public Color public void getBackground () setBackground (Color farbe) 371 Klassenhierarchie Toplevel-Klassen Object (Component) (Container) Panel Applet JApplet Window JWindow Frame JFrame Dialog JDialog 372 Klassenhierarchie Komponenten-Klassen Object (Component) (Container) (JComponent) JComboBox JLabel JList JMenuBar JPanel JPopupMenu JScrollBar JScrollPane 373 Klassenhierarchie Komponenten-Klassen (JComponent) JTable JTree JInternalFrame JOptionPane JProgressBar JRootPane JSeparator JSlider JSplitPane JTabbedPane 374 Klassenhierarchie Komponenten-Klassen (JComponent) JToolBar JToolTip JViewport JColorChooser JTextComponent JTextArea JTextField JPasswordField JEditorPane JTextPane JFileChooser 375 Klassenhierarchie Komponenten-Klassen (JComponent) JLayeredPane JDesktopPane (AbstractButton) JToggleButton JCheckBox JRadioButton JButton JMenuItem JMenu JRadioButtonMenuItem JCheckBoxMenuItem 376 Geerbte Eigenschaften Von den AWT-Klassen werden viele Eigenschaften geerbt. Für die Sichtbarkeit interessant sind: • visible • showing • valid 377 Toplevel-Komponenten Toplevel-Komponenten sind JWindow, JFrame, JDialog und JApplet. JFrame jf = new JFrame ("Titel"); Container bjf = jf.getContentPane (); bjf.add (...); jf.setVisible (true); jf.setVisible (false); jf.dispose (); 378 Schnittstelle RootPaneContainer public Container getContentPane (); public void setContentPane (Container c); public Component getGlassPane (); public void setGlassPane (Component c); public JLayeredPane getLayeredPane (); public void setLayeredPane (JLayeredPane c); public JRootPane getRootPane (); 379 Klasse JRootPane public JMenuBar getJMenuBar (); public void setJMenuBar (JMenuBar c); .................................... ______ ____________________________ 380 SwingSet Suche SwingSet.jar und nimm es in den CLASSPATH, dann $ java SwingSet 381 Beispiel InfoDialog public class InfoDialog extends JDialog implements ActionListener { private JButton knopf; public static void main (String[] args) { InfoDialog d = new InfoDialog ( null, "Informations-Dialog Demo", "Das ist ein Beispiel für eine\n" + "graphische Benutzeroberfläche.\n"); d.setVisible (true); } 382 Beispiel InfoDialog public InfoDialog (Frame elter, String titel, String botschaft) { super (elter, titel, false); Container c = getContentPane (); c.setLayout (new BorderLayout (15,15)); MehrzeilenLabel label = new MehrzeilenLabel (botschaft); c.add (label, BorderLayout.CENTER); knopf = new JButton ("Weg damit"); knopf.addActionListener (this); JPanel p = new JPanel (); p.setLayout (new FlowLayout (FlowLayout.CENTER, 15, 15)); p.add (knopf); c.add (p, BorderLayout.SOUTH); this.pack (); } 383 Beispiel InfoDialog public void actionPerformed (ActionEvent e) { if (e.getSource () == knopf) { this.setVisible (false); this.dispose (); } } 384 Weiter Beispiele • MehrzeilenLabel • JaNeinDialog • AlleKomponenten • RollbaresSchmieren • AlleEreignisse 385 Ereignis-Modell • JDK1.0: Ereignis-Modell basiert auf Vererbung. • JDK1.1: Ereignis-Modell basiert auf Delegation. – Es ist leicht zu lernen. – Saubere Trennung zwischen Anwendungs- und GUI-Code. – Robuster Ereignis-Behandlungs-Code, ”bei dem der Compiler schon viel sieht”. – Gestaltungsmöglichkeiten Weiterleitung. für 386 Ereignis-Flüsse bzw - Ereignis-Modell • Ereignis-Klassen-Hierarchie beginnt bei: java.util.EventObject • AWT-Ereignisse leiten sich ab von der Subklasse: java.awt.AWTEvent • Source und Listener • EventListener Schnittstelle oder • EventListener Adapter 387 Registrierung von Empfängern Source.add<Ereignistyp>Listener (<Ereignistyp>Listener); Mehrere Listener sind möglich. 388 Ereignis-Klassen • Daten sind über set- und get-Methoden zugänglich. • Bei mehreren Listenern und set-Methode wird Ereignis für jeden Listener kopiert. • ID-Nummer sollte > java.awt.AWTEvent.RESERVED_ID_MAX sein. 389 Low-Level Ereignisbehandlung Klasse Component: • processEvent (AWTEvent e) • process<X>Event (AWTEvent e) • enableEvents (long Ereignismaske) 390 public class implements Ereignis-Testprogramm EreignisTester extends JApplet MouseListener, MouseMotionListener, FocusListener, KeyListener { public void init () { this.addMouseListener (this); this.addMouseMotionListener (this); this.addFocusListener (this); this.addKeyListener (this); } public void paint (Graphics g) { g.drawString ("Mause und Tippe in diesem Fenster!", 20, 20); g.drawString (botschaft, 20, 50); } 391 Ereignis-Testprogramm public void mousePressed (MouseEvent e) { botschaft = modusTaste (e.getModifiers ()) + " mousePressed wurde aufgerufen (" + e + ")."; repaint (); } public void mouseReleased (MouseEvent e) { ... } public void mouseEntered (MouseEvent e) { ... } public void mouseExited (MouseEvent e) { ... } public void mouseClicked (MouseEvent e) { ... } public void mouseDragged (MouseEvent e) { ... } public void mouseMoved (MouseEvent e) { ... } public void focusGained (FocusEvent e) { ... } public void focusLost (FocusEvent e) { ... } public void keyPressed (KeyEvent e) { ... } public void keyReleased (KeyEvent e) { ... } public void keyTyped (KeyEvent e) { ... } } 392 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 393 import import ”Hello-World”-Applet java.awt.*; javax.swing.*; public class GutenTagApplet1 extends JApplet { public void paint (Graphics g) { super.paint (g); g.drawString ("Guten Tag", 127, 47); } } 394 ”Hello-World”-HTML-Datei <APPLET code="GutenTagApplet1.class" width=500 height=300> </APPLET> 395 ”Hello-World”-Applet – komplizierter public class GutenTagApplet2 extends JApplet { protected Font zeichenSatz; protected int zeichenGröße = 72; protected Color textFarbe = Color.yellow; private int ovalx = 20; private int ovaly = 20; private int ovalb = 430; private int ovalh = 200; private int arcb = 30; private int arch = 30; public void init () { zeichenSatz = new Font ("sanscerif", Font.BOLD, zeichenGröße); } 396 ”Hello-World”-Applet – komplizierter public void paint (Graphics g) { super.paint (g); g.setColor (Color.blue); g.fillRoungRect (ovalx, ovaly, ovalb, ovalh, arcb, arch); g.setColor (Color.magenta); for (int i = 0; i < 6; i++) g.drawRoundRect (ovalx - i, ovaly - i, ovalb + 2 * i, ovalh + 2 * i, arcb, arch); g.setColor (textFarbe); g.setFont (zeichenSatz); g.drawString ("Guten Tag", ovalx + 25, ovaly + ovalh / 2 + zeichenGröße / 2); } 397 Grundlagen • Ein Applet ist eine Subklasse der Klasse JApplet. • Der Lebenszyklus eines Applets wird durch die vier Methoden init (), start (), stop () und destroy () bestimmt. • repaint (), update (Graphics g) und paint (Graphics g) und paintComponent (Graphics g) 398 • public public public public void void void void repaint repaint repaint repaint Graphik-Methoden () (long ms) (int x, int y, int width, int height) (long ms, int x, int y, int width, int height) • public void update (Graphics g) { g.setColor (getBackground ()); g.fillRect (0, 0, width, height); g.setColor (getForeground ()); paint (g); } • public void paint (Graphics g) 399 Applet-Parameter: Methoden • public String getParameter (String pn) : Sie gibt den Wert des Parameters mit Namen pn als String zurück. • public String[][] getParameterInfo () : WebBrowsers und Applet-Viewer rufen eventuell diese Methode auf, um dem Benutzer die möglichen Parameter anzuzeigen. • public String getAppletInfo () : Diese Methode kann von einer ”Über”-Dialogbox verwendet werden und sollte von jedem Applet implementiert werden. 400 Beispiel Applet-Parameter public void init () { String s = this.getParameter ("Zeichengröße"); try { zeichenGröße = Integer.parseInt (s); } catch (NumberFormatException e) { zeichenGröße = 72; } super.init (); s = this.getParameter ("Textfarbe"); if (s.equals ("Gelb")) textFarbe = Color.yellow; else if (s.equals ("Rot")) textFarbe = Color.red; // --- 401 HTML-Datei <APPLET code="GutenTagApplet3" width=500 height=300> <PARAM name="Zeichengröße" value="36"> <PARAM name="Textfarbe" value="Grün"> </APPLET> 402 APPLET-tag-Attribute codebase code, object archive width, heigth alt name align vspace, hspace 403 Ausschnitt Thread Bewegung weiter: while (true) { // --while (angehalten) { try { sleep (10000); } catch (InterruptedException e) { angehalten = false; } } if (beendet) break weiter; // --- 404 Ausschnitt Applet Aktiv public void init () { bewegung = new Bewegung (); bewegung.start (); bewegung.angehalten = true; } public void start () { bewegung.angehalten = false; bewegung.beendet = false; bewegung.interrupt (); } 405 Ausschnitt Applet Aktiv public void stop () { bewegung.angehalten = true; } public void destroy () { bewegung.beendet = true; bewegung.interrupt (); bewegung.join (); } 406 Ausschnitt Applet Aktiv public void paint (Graphics g) { super.paint (g); for (int i = 0; i < kreise.size (); i++) { ((Oval) kreise.get (i)).male (g); } } 407 Inhalt Intensivkurs Java Einleitung Datentypen Operatoren Kontrollstrukturen Die Java-Klasse Vererbung Ausnahmebehandlung Innere Klassen Threads Streams Netzwerk-Programmierung Graphische Benutzeroberflächen Applets Datenbankanbindung 408 JDBC und weiter • JDBC ist ein low-level API → high-level API Man kann damit SQL-Anweisungen absetzen. • embedded SQL für Java • direkte Abbildung von Tabellen als Java-Klassen (object/relational mapping) • JDBC, ODBC, ADO.NET • einstufige, zweistufige Modelle 409 JDBC-Treiber • Treiber: Klasse Driver • Treiber: http://java.sun.com/products/jdbc • DriverManager.getConnection () 410 JDBC-URL • Standard-Syntax: jdbc:<Subprotokoll>:<Subname> Beispiel: jdbc:postgres://ba-stuttgart.de:47/spielbank • Registrierung von Subprotokollen: Email an [email protected] • ODBC: jdbc:odbc:<Datenquellname>[;<Attributname>=<Attributwert>]* jdbc:odbc:Spielbank;UID=kfg;PWD=Ratatui;CacheSize=20; 411 Treiber laden: • Class.forName ("TreiberKlassenname"); • Class.forName ("TreiberKlassenname") .newInstance (); • System-Eigenschaft jdbc.drivers 412 Verbinding Connection Class.forName ("org.gjt.mm.mysql.Driver"); String url = "jdbc:mysql://nr5:3306/it96"; Connection verbindung = DriverManager.getConnection ( url, "Bozo", "hochgeheim"); 413 Klassen für SQL-Anweisungen • Statement • PreparedStatement • CallableStatement 414 Klasse Statement Statement anweisung = verbindung.createStatement (); ResultSet ergebnis = anweisung.executeQuery ("SELECT a, b, c FROM tabelle"); while (ergebnis.next ()) { int x = ergebnis.getInt ("a"); String y = ergebnis.getString ("b"); float z = ergebnis.getFloat ("c"); // Tu was mit x, y, z ... } ergebnis.close (); anweisung.close (); verbindung.close (); 415 execute... • executeQuery (String sql) • executeUpdate (String sql) • execute (String sql) 416 Klasse ResultSet get<Typ> ("Spaltenname")-Methoden oder get<Typ> (Spaltennummer)-Methoden ergebnis.next () Benannte Kursoren und positionierte Manipulationen sind auch möglich. 417 Beliebig lange Datenelemente SQL: LONGVARBINARY oder LONGVARCHAR kann als Stream gelesen werden. InputStream ein1 = ergebnis.getBinaryStream (spaltennummer); InputStream ein2 = ergebnis.getAsciiStream (spaltennummer); Reader ein3 = ergebnis.getUnicodeStream (spaltennummer); 418 Klasse PreparedStatement PreparedStatement prepAnw = verbindung.prepareStatement ( "UPDATE SP SET QTY = ? WHERE SNR = ?"); set<Typ> (parameternummer, parameterWert) Z.B.: prepAnw.setInt (1, 37); prepAnw.setString (2, "S3"); execute (), executeQuery (), executeUpdate () 419 Klasse CallableStatement CallableStatement prozAnw = verbindung.prepareCall ( "{call prozedurName (?, ?)}"); prozAnw.setInt (1, 25); prozAnw.registerOutParameter (1, java.sql.Types.INTEGER); prozAnw.registerOutParameter (2, java.sql.Types.DECIMAL, 3); ResultSet rs = prozAnw.executeQuery (); // Verarbeite rs int i = prozAnw.getInt (1); java.math.BigDecimal d = prozAnw.getBigDecimal (2, 3); 420 Transaktionen • Transaktionen beziehen sich auf die Verbindung (Connection) • setAutoCommit (boolean) • commit () • rollback () • setTransactionIsolation (int) 421 Objekt-Serialisierung • Kodierung von Objekten in Byte-Ströme • Kodierung von Byte-Strömen in Objekte • kompletter Objektgraph • Serializable oder Externalizable 422 Default-Serialisierung • Marker-Schnittstelle Serializable Klasse java.io.ObjectOutputStream : public final void writeObject (Object ob) throws IOException; Klasse java.io.ObjectInputStream : public final Object readObject () throws OptionalDataException, ClassNotFoundException, IOException; 423 Default-Serialisierung • Rekursiver Aufruf von writeObject bzw readObject zur Serialisierung bzw Deserialisierung des ganzen Objekt-Graphen • Zirkel werden erkannt. • Superklassen werden serialisiert. • Felder sind auch serialisierbar. • transient-Klassenelemente werden nicht serialisiert. 424 Beispiel public class ProgrammiererIn extends Person implements Serializable { // - Konstruktor, zeige, setLaune, setKollegIn private Sprache sprache; private transient String laune; private ProgrammiererIn kollegIn; } 425 Beispiel class Person implements Serializable { public Person (String name) { this.name = name; } protected String name; } class Sprache implements Serializable { public Sprache (String name) { this.name = name; } String name; } 426 Beispiel Serialisierung public class Serialisierung { public static void main (String[] argument) throws IOException { FileOutputStream f = new FileOutputStream (argument[0]); ObjectOutputStream s = new ObjectOutputStream (f); ProgrammiererIn p1 = new ProgrammiererIn ("Gustav", "Java"); ProgrammiererIn p2 = new ProgrammiererIn ("Hanna", "C++"); p1.setLaune ("schlechte"); p2.setLaune ("gute"); p1.setKollegIn (p2); p2.setKollegIn (p1); p1.zeige (); p2.zeige (); s.writeObject (p1); s.writeObject (p2); 427 Beispiel Serialisierung ProgrammiererIn[] fp = new ProgrammiererIn[20]; for (int i = 0; i < 20; i++) { fp[i] = new ProgrammiererIn ("Dummy" + i, "Cobol"); fp[i].setKollegIn (p1); } s.writeObject (fp); s.close (); f.close (); } } 428 Beispiel Deserialisierung public class Deserialisierung { public static void main (String[] argument) throws IOException, ClassNotFoundException { FileInputStream f = new FileInputStream (argument[0]); ObjectInputStream s = new ObjectInputStream (f); ProgrammiererIn p; p = (ProgrammiererIn)s.readObject (); p.zeige (); p = (ProgrammiererIn)s.readObject (); p.zeige (); ProgrammiererIn[] fp = (ProgrammiererIn[])s.readObject (); for (int i = 0; i < 20; i++) fp[i].zeige (); s.close (); f.close (); } } 429 Vor- und Nachbehandlung private void writeObject (ObjectOutputStream aus) throws IOException { // Vorbehandlung des Objekts aus.defaultWriteObject (); // Nachbehandlung des Objekts } 430 Nachbehandlung private void readObject (ObjectInputStream ein) throws IOException, ClassNotFoundException { ein.defaultReadObject (); // Nachbehandlung des Objekts } 431 Beispiel • Name wird in * eingebettet. • writeObjekt muß in Superklasse Person definiert werden. • Laune wird nach dem Lesen auf ”unbestimmte” gesetzt. • Anwendungsprogramme ändern sich nicht. 432 Eigene Serialisierung • Implementiere Schnittstelle Externalizable public void writeExternal (ObjectOutput aus) throws IOException; public void readExternal (ObjectInput ein) throws IOException, ClassNotFoundException; 433 Beispiel public void writeExternal (ObjectOutput aus) throws IOException { String old = name; name = "*" + name + "*"; super.writeExternal (aus); aus.writeObject (sprache); aus.writeObject (kollegIn); name = old; } 434 Beispiel public void readExternal (ObjectInput ein) throws IOException, ClassNotFoundException { super.readExternal (ein); sprache = (Sprache)ein.readObject (); kollegIn = (ProgrammiererIn)ein.readObject (); setLaune ("unbestimmte"); } 435 Klassenversion • Entweder Definition von static final long serialVersionUID = -7440944271964977635L; • oder automatische Vergabe. • serialver 436 Applet • <APPLET>-Tag hat ein Attribut OBJECT zum Laden serialisierter Applet-Objekte. • Initialisierungs-Code wird nicht mehr benötigt. • Konvention: Objekt-Datei hat Erweiterung .ser • appletviewer kann zur Erzeugung von Objekt-Dateien verwendet werden (Stop, Save). 437