Inhalt Intensivkurs Java Einleitung Innere Klassen

Werbung
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
Herunterladen