Javakurs, SS00
Karsten Stahl Martin Steffen
Sommersemester 2000
1 Einführung
Inhalt
Einführung ·erste Schritte ·Programmierumgebung ·einfachste Verwendung der Bibliothek
Literatur:
Aus den Nutshellbuch [Fla99b], dazu verschiedene
Readmes, verschiedene Webpages (cf. die Kursseite
www.informatik.uni-kiel.de/inf/deRoever/SS00/Java/
-
einfach (?)
``in C it is easy to shoot yourself in the foot, in C++ it is easy to
blow your whole leg away'' (Bjarne Stroustrup)
- objektorientiert (klassenbasiert)
- interpretiert
- robust und sicher
- plattformunabhängig und portabel
- effizient (?)
- multithreaded
- implizite Speicherverwaltung (garbage collection)
``explicit memory management has proved to be a fruitful source of
bugs, crashes, memory leaks and poor performance'' (Sun Microsystems,
1995, The Java Language Environment, A White Paper)
Folgendes nach
P. Naughton
-
Jan. 91: "`Stealth project"': Erste
Vorbesprechungen (Joy, Gosling, Naughton ...)
- Juni 91: Arbeit am Oak-Interpreter beginnt
(Gosling), später umbenannt in Java
- August 91: Präsentation erster Ideen vor den Sun-Bossen
- März 93: Hauptstoßrichtung der Oak-Entwicklung wird
interaktives Fernsehen, (Sun will einen Auftag von Time-Warner an
Land ziehen)
- April 93: NSCA Mosaic verfügbar
- Juni 93: Deal mit Time-Warner kippt, SGI bekommt den
Zuschlag
- Sommer 93 -- Frühjar 94 Suche nach Anwendungen
(Consumer-Electronics, Interaktives Fernsehen, OS für Set-Top-Boxen, CDs
Online, Multimedia, OS (Liveoak) ...)
- Juli 94: Entscheidung: ``Anwendung'' von Liveoak
ist das Internet
- September 94: Prototypimplementierung des Browsers
WebRunner beginnt (später HotJava)
- Herbst 94: Bootstrapping: Javacompiler in Java
- Mai 1995: Sun stellt Java und HotJava offiziell auf der
SunWorld '95 vor, Netscape springt auf und will Java lizensieren
- später im Jahr: weitere Firmen, darunter Microsoft,
lizensieren Java:
- Dezember 1995: Javascript von
Sun/Netscape
- ...
- Oktober 1997: Beginn des ersten Java-``Krieges'' (Netscape
vs. Microsoft)
Java: die Speerspitze der Programmiersprachen?
|
-
Statisches Typkonzept
- Typsicherheit (?)
- virtuelle/abstrakte Maschinen
- objektorientiert
- Interfaces
- parametrische/generische Module, parametrische Polymorphie
`` Q: Are there parameterized types (templates)?''
`` A: Not in Java 1.0 or 1.1. However this is being
seriously considered for future versions.'',
(Frequently asked question 6.12 aus
comp.lang.java)1
- Typinferenz
- type casts
- automatische Speicherverwaltung (garbage collection) : Lisp, 60ern
-
Compiler (javac). Sourcecode |® Bytecode
- Interpreter (JVM) (java): interpretiert
Bytecode
- Appletviewer (appletviewer): Spezialform des Interpreters,
interpretiert Applets, die in HTML-Seiten eingebunden werden
können.
Beispiel 1 [Hello World]
public class HelloWorld {
public static void main (String[] args) {
System.out.println ("Hello World!");
};
};
-
HelloWorld.java enthält die Definition der
Klasse HelloWorld.
- javac HelloWorld.java liefert HelloWorld.class
- java HelloWorld führt HelloWorld.class aus.
- appletviewer mypage.html interpretiert alle in die Seite
eingebundenen Applets
Später genaueres zur objektorientierte Programmstrukturierung eingehen,
für's erste soll folgende Charakterisierung genügen:
-
Klasse
-
Progammcode ist in Klassen organisiert.
- reserviertes Wort class
- public-Klasse bestimmt den Dateinamen (mit Extension
java) (d.h., bei > 1 Klassendefinition in einer Datei ist
genau eine davon public, diese bestimmt den Dateinamen.)
- Application: stand-alone Java-Programm, mit
Methode main (public static
void).
- Klassen: Definition von Objekten, d.h., Vereinbarung
von (Objekt-lokalen) Variablen und Methoden, aber keine
Speicherreservierung.
- Objekt
-
Einheit von Daten und Methoden, die auf den
Daten operieren.
- Instanz einer Klasse
- alle Instanzen einer Klasse: gleiche Methoden, aber eigener
Speicherbereich und eigenen Werten der lokalen Variablen
- new instantiiert eine Klasse in ein Objekt, d.h., gibt
die Referenz auf das neue Objekt zurück
- Objekte existieren zur Laufzeit, Klassen zur Compilezeit
- Zugriff nur über Methoden (Kapselung).
-
Application Programming Interface: Javas
Klassenbibliothek
- Organisiert in verschiedene Packages
- Package: Gruppe verwandter Klassen, hierarchisch
aufgebaut (Bsp: package java enthält alle API-Pakete).
- Referenzierung: z.B. java.applet.
java.lang |
Zentrale Klassen. Paket wird
automatisch in jedes Javaprogramm importiert. |
java.applet |
Programmierung von Applets |
jawa.awt |
Graphikunterstützung, GUIs |
java.beans |
wiederverwendbare SW-Komponenten |
java.io |
Input/Output |
java.math |
mathematische Funktionen |
java.net |
Netzprogrammierung |
java.rmi |
Remote method invocation |
java.security |
(Netzwerk-) Sicherheit |
java.sql |
Arbeiten mit Datenbanken |
java.text |
Textformatierung |
java.util |
Sonstige nützliche Klassen (Datentypen) |
... |
etc. |
Table 1: Java API
-
Abkürzung anstelle vollqualifizierter Schreibweise zur
Referenzierung von Klassen
- Gebrauch
-
import package.class
- import package.*
- das Paket java.lang ist grundsätzlich automatisch
importiert. z.B.: die Klasse System kann ohne import
java.lang.* verwendet werden:
- Beispiel: siehe nächste Folie
Beispiel 2 [Importieren]
Durch Importieren der Klassen aus dem Paket java.io hat man
direkten Zugriff auf beispielsweise BufferedReader
import java.io.*; // I/O-Klassen
class Test_Class {
public static void main (String [] args) throws IOException {
BuffererReader stdin =
new BufferedReader (new InputStreamReader (System.in))}}
Anstelle alle Klassen im I/O-Paket auf einmal zu importieren, hätte man
auch die zwei benötigten herauspicken können:
import java.io.BufferedReader;
import java.io.InputStreamReader;
...
-
Applet ¹ stand-alone Programm = Applications
- keine main-Methode, Interpreter sucht stattdessen (u. a.)
nach paint-Methode
- Abgeleitet (durch Vererbung) aus der Klasse
Applet des Pakets java.applet (Vererbung kommt später
genauer)
- Applets werden (i. d. R.) in HTML-Seiten eingebettet und durch
Netbrowser interpretiert.
Beispiel 3 [Applet]
Ein sehr einfaches Beispiel für ein Applet, genauer gesagt, eine
Klasse,
deren Instanzen
Applets sind. Es ist eine
Unterklasse
von Applet.
import java.applet.Applet; // Importieren
import java.awt.*;
public class FirstApplet extends Applet {
public void paint (Graphics page) {
page.drawString ("Hello World", 50, 50);
} // Methode paint
} // Klasse FirstApplet
2 Daten- & Kontrollstrukturen
Inhalt
Struktur der Sprache ·primitive Datentypen ·Schleifen ·bedingte Anweisungen, etc.
Literatur:
Einen hervorragenden Schnelleinsstieg bietet Java in a Nutshell
[Fla99b]. Der folgende Abschnitt baut zu einem Teil
auf diesem Buch auf (Kapitel 2). Wer es gemächlicher und lehrbuchartiger
wünscht, ist mit dem Java Software Solutions
[LL97] gut bedient. In Bezug auf die Spezifika von Java
1.2 ist es ein wenig veraltet.
-
Anzahl reservierter Worte, d.h. von der Sprache
vorbelegte Indentifier. Schlüsselworte für primitive
Datentypen, Kontrollstrukturen, ``Modifierer''.... Manche sind (noch)
ohne Bedeutung
- Kommentare:
// Rest der Zeile ist Kommentar |
wie in C++ |
/* <Kommentar> */ |
wie in C/C++ |
/** Dokumentarkommentar */ |
für javadoc |
- Unicode-Zeichen2 für Identifier, Strings
- kein Präprozessor (also kein #define <KONST>,
#include <File>, #ifdef)
- String für Zeichenketten ist kein primitiver
Datentyp, aber man kann Stringliterale wie gewohnt ("Hello
World") verwenden
|
Werte |
Schlüsselwort |
Bitlänge |
numerisch |
ganze Zahlen, |
byte |
8 |
|
alle mit Vorzeichen |
short |
16 |
|
|
int |
32 |
|
|
long |
64 |
|
Fließkommazahl |
float |
32 |
|
|
double |
64 |
boolesch |
true o. false |
boolean |
1 |
Zeichen |
UNI-Code |
char |
16 |
-
Deklaration/Definition beispielsweise
int i = 5;
boolean b = true;
char c = 'f';
float x = 1234.4f; // !!
<\code>
-
die Operatoren sind:
-
typisiert, und zum Teil überladen
- (partiell) geordnet nach Präzedenz (Bindungsstärke)
- mit unterschiedlicher Assoziation (links/rechts)
- Meist Infix-Notation4
- anonsten C-ähnlich (siehe ausgeteiltes Blatt),
zusätzlich:
-
>>>: Rechtsschift mit 0
- | und & auf boolean: logisches
"`oder"' bzw. "`und"'5
- instanceof
- es fehlen Operationen für Pointerarithmetik
* (Dereferenzierung), &
\\
-
Referenzdatentypen: Objekte und
Arrays
- Manipulation `` by reference'', also über die
Addresse/Referenz.
-
Variablen eines Referenztyps speichern die Referenz, nicht
den Wert. Wertzuweisung kopiert Referenz
- Übergabe der Referenz an Methoden
- == vergleicht, ob auf das selbe Object/Array
verwiesen wird.
- null: Leere Referenz
- Müllabfuhr (garbage collection)
- Aber: keine Dereferenzierung, keine Pointer,
kein Cast von Referenztypen zu primitiven Typen oder
umgekehrt.
-
zu jedem primitiven Datentyp gibt es eine Wrapper-Klasse
- ``das gleiche'' wie die elementaren Werte eines primitiven Datentyps,
nur als Objekte einer Klasse (dem
wrapper)
- Namenskonvention: ähnlich dem Namen des primitiven Datentyps, aber
Großbuchstaben (Byte, Short, ...,
Character)
- Beispiel: Umwandlung (kein cast):
int i = 15;
Integer intobject = new Integer(i);
<\code>
- Nutzen: An manchen Stellen wird ein Objekt erwartet, kein
elementarer Wert6
-
nicht-primitiver Datentyp: Objekte mit
``Spezialsyntax''
- Array der Länge n: indiziert von 0 bis n-1
- Syntax:7
float[] height = new float [25];
height[0] = 20.9f; // nicht 20.9
System.out.println(height.length);
<\code>
- Bound-check zur Laufzeit
- Instantiieren eines Arrays von Objekten:
Speicherreservierung, keine Instantiierung der Objekte
- Initialisierung mit Initialisierungsliste:
String[] zahlen = "eins", "zwei", "drei";
<\code>
- mehrdimensionale Arrays: Arrays von Arrays von...
int fourD [][][][] = new int[10][][][];
// new int[][10][][]; verboten
int twoD[][] = 1, 1,2, 1,2,3;
<\code>
-
kein primitiver Datentyp (sondern Klasse Java.lang.String),
aber
-
es gibt Stringliterale wie gewohnt
- Operator (keine Methode) + zur Konkatenation
von Strings
- implizite Konversion in einen String in
Fällen8 wie:
System.out.println("Die Antwort lautet " + 42);
<\code>
Block |
Gruppierung mit { und }.
; als Trenner |
bedingte Anweisungen |
if |
if (<cond>) <stmnt1> else <stmnt2> |
switch |
switch (expr) {
case value1:
stmnt-list;
case value2:
stmnt-list;
....
};
|
Schleifen |
while |
while (<cond>) <stmnt>; |
for |
for (<init>; <cond>; <incr>) <stmnt>; |
do |
do <stmnt> while (<cond>); |
-
kein goto
- switch: konstante Ausdrücke, und zwar ganze Zahl
oder char; optionaler default-Zweig am Ende. Für
exklusive Auswahl: Zweige (bis auf default) mit
break abschließen!
- break: Verlassen des
Schleifenrumpfes9/des Switchzweiges
- continue: Überspringen des weiteren Schleifenrumpfes
- Es gibt auch gelabelte break/continue
| für die die goto's vermissen.
10. April 2000
3 Objektorientierte Strukturen (1)
Inhalt
Objekte und Klassen ·Vererbung ·Klassenhierarchie ·Überschreiben
Literatur:
Die Lektion baut teilweise auf Kapitel 3 aus [Fla99b]
auf. Siehe auch Kapitel 4 und 8 aus [LL97]. Eine
schöne allgemeine Übersicht und Diskussion über objektorientierte
Sprachmerkmale bietet das Buch Object-Oriented Programming
[Bud97].
Beispiel 4 [Circle]
Der Zustand
eines Kreises als einer Instanz von Circle |
die Koordinaten seine Zentrums und sein Radius | wird in den
entsprechenden Feldern oder Instanzvariablen mit
passendem Typ gespeichert.
public class Circle1 {
// Felder
public double x, y; // Daten = Koordinaten
public double r; // in die Felder
// Methoden
public double circumference() {
return 2 * 3.1415926 * r;
}; //
}; // '{' und `}' zur Gruppierung
-
Objekt: Einheit von Daten (`` fields'') und
Methoden, die auf den Daten arbeiten.
- Instanz einer Klasse (Klasse als "Datentyp" des
Objektes).
- neue Objekte: Instantiierung mittels new11
- Methoden/Feld-Selektion (``Methodenaufruf): mittels
``.''.
Beispiel 5 [Circle]
Zugriff auf den Zustand eines Kreisobjektes
= Instanz von
Circle1 über seine Felder oder Methoden
Circle1 c = new Circle1(); // Instantiierung
c.x = 4.0; // Zugriff auf Felder
c.y = 2.3; // und Methoden mit
c.r = 1.5; // `.'
double a = c.circumference();
Objekte und Klassen: Konstruktoren
|
-
Konstruktor: ``Spezialmethode'' zur
Initialisierung eines Objektes mit dem selben Bezeichner wie
die Klasse
- new ÞAufruf der Konstruktor-Methode.
- Jede Klasse besitzt (mindestens einen) Konstruktor selben Namens,
falls keiner angegeben wird Þ Default-Konstruktor ohne
Parameter (siehe vorheriges Beispiel 5)
- mehrere Konstruktoren mit unterschiedliche Parameterlisten möglich:
Beispiel für `` method overloading''.13
- kein (expliziter) Rückgabetyp
Beispiel 6 [Circle]
Hier das gleiche Beispiel nochmal, diesmal mit (nicht-default)
Konstruktor. Instantiierung
nun mittels Circle2 c = new
Circle2(3.2, 4.5, 1.9).
public class Circle2 {
private double x, y; // private: kommt sp"ater
private double r; // genauer
Circle2 (double _x, double _y, double _r) {
x = _x;
y = _y;
r = _r;
}; // Konstruktor Circle2
//----------------------------
public double circumference() {
return 2 * Math.PI * r; // Konstante der Klasse Math
};
};
Instanz- und Klassenvariablen
|
Variablendeklarationen in einer Klasse (Felder) kann man in
Instanz- und Klassenvariablen unterteilen
-
bisher und für gewöhnlich: Instanzvariable: eine Kopie
pro Instanz
- Klassenvariable oder auch statische Variable:
-
eine Kopie der Variable pro Klasse
- Schlüsselwort static
- Zugriff: ebenfalls mittels `.', allerdings über den
Klassennamen: <classname>.<var_name>14
- sie entsprechen globale Variablen mit dem Klassennamen
als Diskriminator
(z.B. Math.PI)15
- lokale Variablen (innerhalb einer Methode) dürfen
nicht statisch sein
Beispiel 7 [Anzahl der Instanzen]
Sei ein Kurs durch die Menge seiner Teilnehmer modelliert. Die
Klassenvariable freiePlaetze drückt einen
globalen
``Zustand'' des Kurses aus.16
public class Teilnehmer {
public static int freiePlaetze = 10;
public String name;
public int matrikelnummer;
Teilnehmer(String n, int m) {
name = n;
matrikelnummer = m;
freiePlaetze--; // einer weniger frei
}; // Konstruktor
};
Klassenmethoden, statische Methoden
|
Analog der Situation bei Feldern unterscheidet man Instanz- und
Klassenmethoden.
-
bisher (fast) nur Instanzmethoden
- Klassenmethoden oder auch statische Methoden
-
Schlüsselwort static (``Modifier'')
- Zugriff: über den Klassenbezeichner (analog
Klassenvariablen)
- Wichtig: kein impliziter this-Parameter!
- Beispiel: die Klasse java.lang.Math enthält nur statische
Methoden17
Initialisierung von Klassenvariablen
|
Lebensende von Objekten: Müllabfuhr und Finalisierung
|
-
implizite, automatische Speicherverwaltung: Garbage
Collection (in Ruhephasen und bei Bedarf)
- ``Finalization'': spezielle Methode
(finalize()) von Objekten, aufgerufen bevor der Speicher für
das Objekt freigegeben wird.
- Verwendung: Freigabe von Systemresourcen, die nicht
automatisch | wie der Speicher | verwaltet werden, z. B.:
Schließen von Dateien, Abbau von Netzverbindung etc.
Unterklassen und Vererbung
|
Beispiel 8 [Konto]
public class Konto {
int kontostand;
String inhaber;
Konto (String name, int i) {
kontostand = i;
inhaber = name;
};
Konto (String name) { // konstruktor-overloading
kontostand = 0;
inhaber = name;
};
/* Konto (){
kontostand = 0;
inhaber = "";
};
*/
//-----------------------------------------
public void einzahlen (int betrag) {
kontostand += betrag;
};
public void auszahlen (int betrag) {
kontostand -= betrag;
}
public int wieviel () {
return kontostand;
};
};
Beispiel 9 [Sparkonto]
Ein Sparkonto
sei eine besondere Art von Konto, die auch noch
Verzinsung
bietet.
public class Sparkonto extends Konto { // Unterklasse
double z_faktor;
double ueberziehungsz_faktor;
Sparkonto (double z_satz, double z_satz2, String name, int i) {
super(name,i);
z_faktor = 1+ z_satz /100;
ueberziehungsz_faktor = 1+ z_satz2/100;
};
Sparkonto (double z_satz, String name) {
super(name); // this.inhaber = name;
// w"are falsch
z_faktor = 1 + z_satz/100;
};
/* Sparkonto(double rate) {... ginge nicht, denn
super hat kein Konto()-Konstruktor */
// ------------------------------------------------
public void verzinsen() {
kontostand = (int) (z_faktor * kontostand);
};
public void auszahlen (int betrag) { // "Uberschreiben
if (kontostand >= betrag)
kontostand -= betrag;
};
};
-
die Klassen von Java bzw. der Klassenbibliothek formen eine
Hierarchie
-
mit Wurzel java.lang.Object
- final-Klassen haben keine Unterklassen
- Kette der Konstruktoren (constructor chaining,
bei der Instanziierung; explizit oder implizit. Ausnahme: man umgeht es
mittels this.
- bis auf Object: jede Klasse hat eine Oberklasse
-
explizit mittels extends
- falls extends fehlt: Unterklasse von Object
- eine Klasse kann beliebig viele Interfaces
implementieren.19 Beachte: dies
ist keine Mehrfachvererbung
Überschreiben von Methoden
|
-
Überschreiben (overriding): Kerneigenschaft
oo-er Sprachen
- verschiedene Worte: dynamischer Methodenaufruf, dynamic
dispatch, späte20 Bindung, message passing,
meinen alle (so gut wie)21 das selbe:
Methodenaufruf läßt sich als Prozeduraufruf mit später
Bindung verstehen
- static-, private- und final-Methoden
können nicht überschrieben werden
- Referenzierung der überschriebenen Methode und der überschreibenden
Klasse mit super:
super.<methode>
- "`überschriebene"' Felder:
( shadowed), am besten vermeiden
Beispiel 10 [Überschreiben]
Hier ein Beispiel, welches Vererbung mit Überschreibung von Feldern und
Methoden auf etwas merkwürdige Weise kombiniert.
class A {
int i = 1;
int f() { return i;}
};
public class B extends A {
int i;
int f() {
System.out.println("i = " + i);
i = super.i + 1;
System.out.println("i = " + i);
System.out.println("super.f() = " + super.f());
return super.f() + i;
};
};
public class Main {
public static void main (String[] args) {
B b = new B();
System.out.println("i = " + b.f());
};
}
Die Ausgabe Beim Ausführen von main ist (bis auf die
``newlines''):i=5; i=2; super.f() = 1; i = 3.22 Das erste i ist klar, es ist einfach die in
B vorhanden Version von i die die aus A überschreibt (genauer
gesagt überschattet (shadowed)). Die Zuweisung
danach setzt i dann auf 2, wegen super, der Wert von i in
A ändert sich damit nicht. Das Ergebnis des Aufrufes von
super.f ist interessant, es greift auf die
Variable von A zu und liefert das, wie gesagt, unveränderte i =
1. Der Returnwert 3 am Ende sollte damit klar sein.
Wenn wir das Beispiel ändern indem wir die Zeile int
i = 5; aus B entfernen, erhalten wir folgendes Ergebnis:
i = 1; i = 2; super.f() = 2; i = 4. Das erste i ist klar: da
B das Feld i nicht einführt, erbt es das aus A mit dem Wert 1.
Auch die nächste Ausgabe ist klar: 1+1 = 2. Interessant die Ausgabe
von super.f, diesmal ergibt es den Wert 2, da
wir diesmal nur eine Kopie
des Feldes in A und B haben. Die
Rückgabe von 4 ist dann klar.
Beispiel 11
class A {
public int x = 3;
public void test () { System.out.println("A"); }
public void test2 () { System.out.println("x = " + x); }
};
class B extends A {
public int x = 4;
public void test () { System.out.println("B"); }
public void test2 () { System.out.println("x = " + x); }
};
public class Main2 {
public static void main (String[] args) {
A a = new A();
A b; b = new B(); // die wichtige Zeile!
b.test();
b.test2();
System.out.println("b.x = " + b.x);
}
}
Dieses Beispiel zeigt klar den Unterschied zwischen
statischer und dynamischer Bindung und auch den
Unterschied zwischen Deklaration einer Referenzvariablen und
dem Instanziierung den Objekts: Felder sind statisch gebunden
und Methoden dynamisch.23
Die Ausgabe des Programms lautet B; x = 4; b.x = 3. Der Aufruf
der Methode test an b liefert die Methode in B, das selbe
für den Aufruf von test2. Das interessante (oder krumme) ist
der Unterschied zu b.x der dadurch kommt, daß b als vom
Typ/Klasse A deklariert ist! Schriebe man
B b anstelle dessen, wäre die Ausgabe von
b.x ebenfalls 4!24
-
Wichtiges OO-Merkmal: Zugriff auf Daten (möglichst) nur über
Methoden
-
Datenabstraktion, Strukturierungs- und Scoping-Konzept ...
erlaubter Zugriff |
Sichtbarkeit |
|
public |
protected |
default |
private |
selbe Klasse |
Ja |
Ja |
Ja |
Ja |
selbes Paket |
Ja |
Ja |
Ja |
Nein |
Unterklassen (anderes Paket) |
Ja |
Ja |
Nein |
Nein |
beliebige Klasse |
Ja |
Nein |
Nein |
Nein |
Table 2: Sichtbarkeitsmodifikatoren
-
Merke: Geerbte Variablen und Methoden behalten ihre
Sichtbarkeitsstufe
- Konstruktoren sind public (und werden nicht
vererbt)
- protected: werden an Unterklassen vererbt
Ein paar Daumenregeln für die verschiedenen
Sichtbarkeitsstufen
-
public: für Methoden und Konstanten, die der Benutzer sehen
soll. Sehr sparsam bei Feldern25
- protected: Unwichtige für die Benutzung der Objekte,
aber wichtig für jemand, der ein Paket um Unterklassen außerhalb des
Paketes erweitert
- default (auch Paket-Sichtbarkeit): Methoden, die zur
Kooperation innerhalb eines Paketes notwendig sind
- private: lokale verborgene Definitionen innerhalb einer
Klasse
-
abstrakte Klasse: nicht instantiierbar
(abstract)
- abstrakte Methode: ohne Rumpf. nur Signatur
- Zusammenhang:
-
``konkrete'' Klasse mit abstrakten Methoden: verboten
- abstrakte Klasse mit ``konkreten'' Methoden: erlaubt
- konkrete Unterklasse einer abstrakten Klasse muß die
abstrakten Methoden (typkonform)
implementieren26
- Nutzen:
17. April 2000
4 Ausnahmebehandlung
Inhalt
Verwendung von Ausnahmen ·Definition eigener Ausnahmebehandlung
Literatur:
Den entsprechenden Abschnitt aus [Fla99b] oder
Abschnitt 14.1 aus [LL97]. Deneben unter anderem die
Klassen java.lang.Throwable, java.lang.Error,
java.lang.Exception.*
-
nicht alle unerwünschten Situationen können statisch
überprüft und abgefangen werden ÞExceptions
- disziplinierte Art, den Kontrollfluß abhängig
vom (Fehler- ) Verhalten zu steuern
- Zur Steuerung:
-
throw: Signalisierung einer Ausnahmesituation
ÞVerlassen des gewöhnlichen Kontrollflusses
- catch: Definition der Reaktion auf eine
Ausnahme
- Nutzen:
-
saubere Trennung von Normal- und Ausnahmeverhalten,
d.h. Ausnahmebehandlung getrennt vom Rest anpassbar (vorteilhaft auch
bei der Verwendung fremder Klassen/APIs)
- Debugging einfacher
- Typsicherheit
Beispiel 12 [Division durch Null]
class Div {
public static int division (int z, int n) {
return z/n; // Zeile 3
};
};
public class Main {
public static void main (String[] args) {
int nenner = 0;
int zaehler = 0;
System.out.println(Div.division(zaehler, nenner)); // Zeile 11
};
};
Ergibt als Ausgabe folgende Aufrufstruktur auf dem Stack:
java.lang.ArithmeticException: / by zero
at Div.division(Main.java:3)
at Main.main(Main.java:11)
Process Main exited abnormally with code 1
Die Ausnahme ist eine Instanz von ArithmeticException, einer
Klasse aus aus java.lang.
Beispiel 13 [Division durch Null (II)]
Der folgende Code zeigt, wie man den Divisionsfehler abfangen |
und hier in eher nicht-empfehlenswerter Weise ignorieren |
kann:28
class Div {
public static int division (int z, int n) {
return z/n;
};
};
public class Main2 {
public static void main (String[] args) {
int nenner = 0;
int zaehler = 0;
int ergebnis = 0; // vorbelegen
try {
ergebnis = Div.division(zaehler, nenner);
}
catch (ArithmeticException e) {
System.out.println("Mir egal, ich rechne weiter");
};
System.out.println(ergebnis);
};
};
Ein klein wenig informativer
wäre bereits die Ausgabe
System.out.println(e + ", trotzdem rechne ich weiter");
Erzeugen und Definieren von Ausnahmen
|
-
Neben Abfangen und Behandeln kann man Ausnahmen auch
Beispiel 14 [Ausnahmen]
class MyException extends Exception {
int wert;
MyException(int i) { // Konstruktor
wert = i;
};
public int get_wert() {
return wert;
};
};
public class Main {
public static void main (String[] args) {
int x;
try
{Main.unsafe_method(0);}
catch (MyException e) {
System.out.println("MyException mit wert = " +
e.get_wert());};
};
public static void unsafe_method(int i) throws MyException {
if (i == 0) {throw (new MyException (i));}
else System.out.println("OK");
};
};
5 Objektorientierte Strukturen (2)
Inhalt
Interfaces ·Pakete ·innere Klassen
Inhalt
Während im ersten OO-Abschnitt Merkmale von Java behandelt wurden, die
in ähnlicher Form in vielen anderen objektorientierten Sprachen auch zu
finden sind, geht es hier um mehr Java-spezifische Dinge. Nachlesen kann
man es in Kapitel 3 aus [Fla99b]. Über Interfaces
und Pakete findet sich auch in [LL97] etwas.
Hier einige Dinge, die ich nicht erzählt habe und die wir (bis auf die
Casts) vermutlich nicht brauchen, beziehungsweise die später kommen.
-
Vorwärts-Referenzen erlaubt
- Schlüsselworte: native, transient,
volatile, synchronized
- final-Modifikator:
-
Klassen: keine Unterklassen
- Methoden: nicht überschreibbar
- Variablen (kein Schreibzugriff). In Java 1.1 auch
anwendbar auf Methodenparameter und lokale Variablen
Dies & Das (2): Typumwandlungen
|
-
Typumwandlungen: ein Programmfragment kann mehrere
``Typen'' besitzen, in Objekt Instanz mehrerer Klassen sein
(instanceof) Þ Polymorphie
- nur zwischen Referenztypen oder zwischen nicht-Referenztypen.
- Bei elementaren Datentypen
-
Narrowing: Informationsverlust, z.B: von
float nach int)
- Widening: umgedreht
- drei Arten
-
in Wertzuweisungen und Methodenaufrufen:
implizit, nur Widening erlaubt ( Subsumption)
- Arithmetische Promotion (z.B. in 3.0 / 3)
- Explizite Umwandlung (type casts):
-
Schönheitsfehler im Typsystem:
Laufzeittypüberprüfungen
- Syntax: (type) value
Beispiel 15 [Casts]
....
Konto k = new Konto("Tick", 500);
Konto k2 = new Konto("Trick", 1000);
Sparkonto sk = new Sparkonto(10, "Track");
k = sk; // Impl. Umwandlung des sk
((Sparkonto)k).verzinsen(); // Cast
((Sparkonto)k2).verzinsen(); // Cast
-
Interface: enthält abstrakte
Methoden29 und Konstanten
(static final)
- Default: Methoden des Interfaces sind public
- nicht instantiierbar
- @ Signatur der Instanzen einer Klasse
- Klasse implementiert ein Interface (implements)
-
muss typkonforme Implementierung aller
Methoden liefern30
- Konstanten werden ``geerbt''
- mehrere Interfaces erlaubt, aber: ¹
Mehrfachvererbung
- Kombination mit Unterklassenbildung möglich
- Syntax
<class1> implements <interf1>, <interf2>
extends <class2>
- Verwendung als Typ eines formalen Parameters: public void
mymethod (MyInterface arg) {.....}
- Subinterfaces (mittels extends). Wichtig
wiederum: ein Interface kann mehrere Interfaces erweitern
-
dreistufige Hierarchie: Pakete ÞKlassen ÞMitglieder31
- Konvention: Paketnamen oft mit ``.'' separiert und
Paketnamen = Verzeichnispfad
- Vorschlag zur weltweiten Namensvergabe von
Klassen:32
|
|
de.uni-kiel.informatik.users.ms.classes. |
|
|
Paket, Verzeichnis users/ms/classes |
|
|
|
|
|
- Schlüsselwort package: zu Beginn einer Quelldatei, gibt
die Zugehörigkeit der Klasse zum Paket an
- import: relativ zum CLASSPATH (import
package.* oder import package.class)
- Zugriffsrechte: (Siehe auch
Tabelle 2 auf Folie ??)
-
Paket: über Zugriffsrechte (File/Netz)
- Klassen im Paket: zugreifbar für alle anderen Klassen
im Paket, public-Klassen auch außerhalb des Paketes
- Klassen mitglieder: innerhalb des Paketes,
es sei denn sie sind private
- Innerhalb einer Klasse: freier Zugriff der Mitglieder
untereinander.
- Klassenmitglieder einer Klasse A zugreifbar in B eines
anderen Paketes, falls
-
A public und das Mitglied public, oder
- B Unterklasse von A und das Mitglied protected
-
innere Klassen: wichtige Spracherweiterung in
JDK 1.1
- oft verwendet in den 1.1-API-Klassen, vor allem im
Event-Modell
- bisher: Klassen definierbar in genau einem Kontext: an
oberster Stufe in einem Paket33
- Vier neue Arten von Klassen = vier neue
Kontexte
-
geschachtelte Top-level Klassen:
- nicht-top-level Klassen
-
Klassen in Klassen: member Klassen
- Klassen in Methoden: lokale Klassen
- Klassen ohne Namen: anonyme Klassen
- keine Änderung des Laufzeitsystems (Java Virtual
Machine), d.h. syntaktischer Zucker,
Quellcodetransformation
Geschachtelte Top-level Klassen/Interface
|
-
``statische'' Klasse innerhalb einer anderen, als
Mitglied
- static-Modifikator
- geschachtelte Interfaces sind implizit statisch
- Semantik: genau wie andere Klassen, nur der Name der
Klasse enthält die umgebende Klasse.
- Þfeinere hierarchische Aufteilung des Namensraumes
für Klassen, weniger Namenskonflikte
- geht für Klassen und Interfaces
- Benutzung von import wie bei Paketmitgliedern:
import Klasse_aussen.Klasse_innen
-
Member-Klasse: nicht-statisches Mitglied
einer äußeren Klasse (mit anderem Namen)
- darf keine statischen Mitglieder enthalten
- Interfaces nicht möglich (immer statisch)
- Instanzen sind mit einer Instanz der umgebenden Klasse
assoziiert ÞZugriff auf deren
Instanzmitglieder, d.h. des Objektes
- Verwendung: Hilfsklassen der äußeren Klasse
- Problem:
- member-Klassen sind schachtelbar
- etwas Abartiges: Top-level Klasse kann eine Memberklasse
erweitern34
- Member-Klassen: Gültigkeitshierarchie, getrennt von der
Unterklassenhierarchie
- Sichtbarkeiten: wie üblich (public allerdings selten)
Beispiel 16 [Member]
Folgendes Beispiel zeigt das Absuchen einer Liste unter Verwendung
java.util.Enumeration. Wollten wir den Enumerator nicht
als Member, sondern als getrennte top-level Klasse definieren, müssten
wir ihm die LinkedList als Argument des Konstruktors
mitgeben. Hier kann mit head direkt auf das
Feld der umgebenden Klasse zugegriffen werden.
import java.util.*;
public class LinkedList4 {
public interface Linkable removeHead() { // top-level nested
public Linkable getNext();
public void setNext(Linkable node)
};
Linkable head;
public void addToHead(Linkable node) {....};
public Linkable removeHead() {....};
public Enumaration enumerate() {return new Enumerator()};
private class Enumerator implements Enumeration { // Member!
Linkable current;
public Enumerator() {current = head;} // Konstruktor
// ------------------
// 2 Methoden des Enumeration-interfaces
public boolean hasMoreElements() { return (current != null);}
public Object nextElement (){
if (current == null)
throw NoSuchElementException("LinkedList");
Object value = current;
return value;
}
}
}
-
innere Klasse innerhalb eines Blockes
- sichtbar nur innerhalb des definierenden Blocks, analog lokalen
Variablen, beispielsweise eine Klasse innerhalb einer Methode
- können auf Mitglieder der umschließenden Klasse
zugreifen, insbesondere auf final lokale Variablen und Parameter
innerhalb des Blockes35
- Verwendung oft als sog. Adapterklassen, speziell im
Eventmodell von Java 1.1 (Event Listener als
Implementierung für listener interfaces)
Beispiel 17 [Lokale Klasse]
import java.util.*;
public class LinkedList4 {
public interface Linkable removeHead() { // top-level nested
public Linkable getNext();
public void setNext(Linkable node)};
Linkable head;
public void addToHead(Linkable node) {....};
public Linkable removeHead() {....};
public Enumaration enumerate() {
class Enumerator implements Enumeration {
Linkable current;
public Enumerator() {this.current =
LinkedList.this.head;}
// ------------------
// 2 Methoden des Enumeration-interfaces
public boolean hasMoreElements() { return (current != null);}
public Object nextElement (){
if (current == null)
throw NoSuchElementException("LinkedList");
Object value = current;
current = current.getNext();
return value;
}
}
}
}
Beispiel 18 [Anonyme Klasse]
Im folgendes Beispiel implementiert eine anonyme Klasse das
Interface
FilenameFilter (mit Methode accept)
aus dem Paket java.io.36
import java.io.*;
public class Lister{
public static void main(String[] args) {
File f = new File(args[0]);
String[] list = f.list(new FilenameFilter() {
public boolean accept(File f, String s) {
return s.endsWith(".java");
};} // Ende der anon. Klasse
);
for (int i = 0; i < list.length; i++)
System.out.println(list[i]);
};
};
Klasse |
Beschreibung |
top-level |
Paketmitglied |
K/I |
Java-1.0, direkt interepretierbar durch die VM |
|
geschachtelt |
K/I |
static innerhalb einer anderen
top-level Klasse |
|
Innere Klasse |
Member-Klasse |
K |
nicht-statisches Mitglied, besitzt umschließende
Instanz, mit Zugriff auf deren Mitglieder, neue Syntax für
new, super, this. Statische Mitglieder
verboten |
|
Lokale Klasse |
K |
innerhalb eines Blocks, Zugriff auf Mitglieder der
umschließenden Klasse + final lokale Variable,
neue new-Syntax |
|
Anonyme Klasse |
K |
namenlose lokale Klasse,
eine Instanz, kein Konstruktor |
|
Table 3: Arten von Klassen
8. Mai 2000
6 Input/Output
Inhalt
Zu jeder Sprache gehören Fähigkeiten zur Datenein- und ausgabe. Neben
den umfangreichen Interaktionsmöglichkeiten auf GUI/Event-Basis, stellt
die Klassenbibliothek auch Ein- und Ausgabe über Ströme zur
Verfügung.
Literatur:
Die Rohinformation steht natürlich in den Klassen des Paketes
java.io.*. Daneben Abschnitt 3.3 aus
[LL97].
Bemerkung: Da wir nun verstärkt in die Klassen der APIs
einsteigen, wird es von nun an nicht mehr möglich sein, mehr oder minder
das gesamte Material | alle Klassen und deren Methoden | vorzustellen
oder auch nur zu erwähnen. Für die Lösung der Aufgaben wird es
deswegen z.T. notwendig sein, die Klassenbibliothek selbstständig zu
Rate zu ziehen. Die Klassenbibliothek ist online verfügbar.
-
I/O nicht im Java-Kern, sondern mittels geeigneter Klassen.
relevantes Paket: java.io
- einfachste Ausgabe auf stdout:
System.out.println(....)37
- Quelle für Input oder Output: Strom (stream)
- drei vordefinierte Ströme (byte-Ströme):
-
System.in (meist Keyboard)
- System.out (meist Screen)
- System.err (meist Screen)
- Escape mittels
\
(Liste \b \t \n \r \" \' \\
)
- Input- oder Output- Puffer: temporärer Speicher (wg.
Effizienz)
- Leeren des Ausgabepuffers: flushing, explizit
durch flush, meist durch println, nicht
aber durch print.
-
Aufgaben
-
Lesen/Schreiben von Dateien
- Lesen und Informationsgewinnung von Verzeichnissen
- Bereitstellung von vordefinierten Strömen
- Unterstützung bei der Definition eigener Ströme
- Strom: Objekt, welches sequentielles Lesen
und Schreiben erlaubt.
- die Klasse enthält in der Hauptsache viele Stromklassen
- vier Hauptvertreter, siehe
Tabelle 4, die spezielleren Klassen sind jeweils
Unterklassen davon.
- System.in : InputStream, und System.out
und System.err:
PrintStream38
|
Input |
Output |
Byte |
InputStream |
OutputStream |
Character |
Reader |
Writer |
Table 4: Übersicht über Stromklassen
Ein/Ausgabe: wichtige Klassen
|
Beispiel 19 [Buffered reader]
Das Beispiel zeigt, wie man Text vom stdin
lesen kann. Um von
System.in lesen zu können, muß man die Eingabe
`` puffern''
import java.io.*;
public class Echo {
/**
* Einfachstes Beispiel fuer Lesen vom stdin.
**/
public static void
main (String[] args) throws IOException {
BufferedReader stdin =
new BufferedReader
(new InputStreamReader (System.in));
String message;
System.out.println("Bitte String eingeben: ");
message = stdin.readLine(); // Meth. des BufferedReader
System.out.println("Echo: \"" + message + "\"");
};
};
-
File ist die wichtigste nicht-Stromklasse
-
Repräsentiert den Namen eines Files/Verzeichnisses
- stellt Fileoperationen darauf zur Verfügung (Kopieren, Umbenennen,
Auflisten des Verzeichnisses ...)
- Wahlfreier (¹ sequentieller) Zugriff: RandomAccessFile
- Exeptions: IOExceptions und Unterklassen für
speziellere I/O-Ausnahmen
7 Applets und Graphik
Inhalt
Es geht um die Programmierung von Applets, das Zeichnen von Graphiken,
Parameterübergabe. (Zu Animation und Threads, die man für die Animation
braucht, kommt später, falls noch Zeit ist, genaueres.)
Literatur:
Die Rohinformation zu diesem Abschnitt bieten die Klassen aus dem Paket
java.applet und aus java.awt.Graphics. Dazu Kapitel 7
aus [Fla99b], Kapitel 6 aus dem alten
[Fla97b], Kapitel 4 aus
[Fla97a] oder Kapitel 7 aus
[LL97].
-
Applets: Unterklassen von java.Applet41
- Applets stehen unter der Kontrolle des
Appletviewers/Browsers
-
Þ keine main()-Methode notwendig
- Þ keine Command-line-Parameterübergabe,
dafür
<PARAM>
-tags
- Þ eine Reihe von Standardmethoden, die der
Appletviewer aufrufen kann, wie z.B. paint und die
überschrieben werden
- Þ Applet muß auf diese Methodenaufrufe prompt
antworten, d.h., für Animationen benötigt es
Threads.
- Hierarchie:
Object => Component => Container => Panel => Applet
|
viele (auch) für Applets wichtige Methoden finden sich in vor allem
Component
- Sonstiges:
-
Sicherheitseinschränkungen für Applets
- digitale Signaturen
Wichtige Methoden bei Applets
|
Name |
Ausführung bei |
typische Verwendung |
init() |
Laden des Applets |
Initialisierung, Parameterübergabe. Funktion
ähnlich einem Konstruktor |
destroy() |
Unload |
Recourcenfreigabe |
start() |
Sichtbar-werden |
Malen, Starten der Animation |
stop() |
Unsichtbar-werden |
Unterbrechen der Animation |
getAppletInfo() |
|
Darstellbar in Dialogboxen |
getParameterInfo() |
|
Parameter des Applets |
Aus Oberklassen
(Object => Component => Container => Panel => Applet) |
repaint(_) |
|
(Component),
ruft update auf, welches den Bildschirm löscht und
paint aufruft |
paint(Grapics) |
|
Malen (Container) |
print(Graphics) |
|
Drucken |
Table 5: Wichtige Methoden ``an'' Applets
Beispiel 20
import java.awt.Graphics;
public class Lebenszyklus extends java.applet.Applet {
StringBuffer buffer = new StringBuffer();
public void init () {resize(500, 20);addItem("Initializing...");};
public void start (){addItem("Starting ...");};
public void stop(){addItem("Stop...");};
public void destroy(){addItem("preparing for unloading");};
public void addItem(String meldung) {
System.out.println(meldung);
buffer.append(meldung);
repaint();
};
public void paint(Graphics g) {
g.drawRect(0,0,getSize().width -1, getSize().height -1);
// size deprecated in 1.2
g.drawString(buffer.toString(), 5, 15);
};
};
Häufig in Applets verwendete Methoden
|
Die Klasse Applet stellt auch Methoden zur Verfügung, die man
häufig in Applets brauchen kann.
Image |
getImage(URL) |
Laden von Bildern |
String |
getParameter(String) |
für Parameterübergabe aus HTML-Seite |
URL |
getDocumentBase() |
Url der HTML-Seite |
URL |
getCodeBase() |
Url der Klasse |
|
... |
|
Table 6: In Applet definierte Methoden (Auswahl)
Applets als Stand-alone Programme
|
-
Applets müssen immer irgendwo eingebettet sein
- dies wird jetzt nicht vom Appletviewer/Browser gemacht: Þ Frame selber erzeugen (auch Größe setzen)
42
- Darstelle des Frames: show
- Aufrufen der Applet-init-Methode durch main
Beispiel 21 [Standalone Applet]
Erweitert (und vereinfacht) aus [Fla97a]
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class StandaloneScribble extends Applet {
public static void main (String[] args) {
Frame f = new Frame();
Applet a = new StandaloneScribble();
f.add(a, "Center");
a.init();
f.setSize(400, 400);
f.show(); // show l"a"st einen Frame erscheine
f.setBackground(bgcolor);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);};
});
}; // end of main
public void init() { // auch als applet verwenbar
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
lastx = e.getX(); //
lasty = e.getY();
};
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
Graphics g = getGraphics ();
int x = e.getX();
int y = e.getY();
g.setColor(StandaloneScribble.this.drawcolor);
// wiederum: this alleine geht nicht!
g.drawLine(lastx, lasty, x, y);
lastx = x; lasty = y;
};
});
Button b = new Button("Blau");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawcolor = Color.blue;
};
});
this.add(b);
};
protected int lastx, lasty;
protected static Color bgcolor = Color.white;
protected Color drawcolor = bgcolor;
};
-
Instanzen von java.awt.Graphic sind
`` bemalbare'' Oberflächen mit kartesischen
Pixel- Koordinaten43
- Grahpics: abstr. Basisklasse aller "`bemalbaren"'
Komponenten
- nicht direkt instantiierbar ( Konstruktor ist
protected)
- neue Graphik:
-
Component.getGraphics()/Image.getGraphics(_)
- Kopieren: Graphics.create(_)
- Methoden zum Zeichen verschiedener Dinge44 (Strings, Linien,
Ellipsen, Rechtecke ...)
- zwei Modi: Normal oder XOR (zweimal XOR
löscht wieder)
Figure 1: Koordinatensystem
Graphische Elemente: Fonts, Farben & Cursor
|
-
Font in der Klasse
java.awt.Font45
-
drei Bestimmungsstücke als Konstruktorparameter: Name,
Stil, Größe (String, int,
int)46
- Klasse FontMetrics: Bestimmung verschiedene
Maße für Fonts
- setFont: (in Graphic) setzt den aktuellen Font
einer Graphik
- Farben in der Klasse java.awt.Color
-
vordefinierte Farben als
``Konstanten''47
- Konstruktoren mit RGB-Parameter
(rot-grün-blau)48
- Umrechnung in HSB-Farbmodell möglich
- Cursor in der Klasse java.awt.Cursor
-
Verschiedene Standardcursors, insbesondere
DEFAULT_CURSOR.
- Übergebbar der Methode setCursor(Cursor:c)
8 Graphische Benutzerschnittstellen (GUIs)/ AWT
Inhalt
AWT ·Übersicht ·``Components'' ·Layout
Literatur:
Dieser Abschnitt diskutiert Auszüge aus dem Paket java.awt
Abstract windowing toolkit. Das Paktet ist sehr
groß, sodaß wir nur einen kleinen Teil ansprechen können. Bestimmte
Teile (Graphiken, Fonts, Farben) wurden auch bereits in einem
vorangegangenen Abschnitt besprochen)
Die GUI-Libraries haben sich unter allgemeiner Begeisterung und nicht zum
ersten zum ersten Mal geändert. Sie haben jetzt die schöne Bezeichnung
Java Foundation Classes (JVC) bekommen. Näheres zu
Swing vielleicht später.
Weitere Informationen finden sich in Kapitel 8 im alten Nutshell-Buch.
Aus Gründen der Geldschneiderei, gibt es nun ein extra-Nutshell buch
für die AWT: [Fla99a]. von
[Fla99b], Kapitel 6 aus
[Fla97a] oder Kapitel 10 aus
[LL97]. Events sind eng mit der Programmierung von GUIs
verbunden, kommen aber später noch genauer.
-
Bestehend aus den Paketen:
-
AWT: Modernes GUI-Toolkit, fast aufwärtskompatibel mit
JDK 1.1
- Swing: noch moderneres49 GUI-Toolkit, erweitert AWT
- Für applets, die von (den meisten)
Browsern verstanden werden sollen: besser AWT
- Java 2D (1.2) Graphic
- neue API's für Drucken und Datentransfer:
( java.awt.print,
java.awt.datatransfer)
- Applets
Übersicht über das Abstract Windowing Toolkit
|
Wir können vier wichtige Gruppen von Klassen aus dem AWT
ausmachen
-
Graphik: Klasse Grapics zum Pixelmalen (siehe
vorangeganenen Abschnitt)
- graph. Komponenten:50 Klasse
Component (und MenuComponent) und ihre
Unterklassen: Interfaceelemente zur Interaktion
- Component: wichtiges (abstraktes) GUI-Element
-
Knöpfe
- Listen
- Menues
- Scroll bars
- Dialoge ...
- Layout: zur Anordnung von Komponenten innerhalb von
Komponenten.
- Events: Ereignisse, zur Interaktion mit der Oberfläche
notwendig.
-
Erzeugen der Komponenten
-
wie üblich instantiieren mit new (z.B. Button
quit = new Button("Quit")),
- passiert meist zu ``Beginn'' der umgebenden Komponente (in
init(), im Konstruktor)
- Hinzufügen der Komponenten in einen Behälter
-
-
führt oft zu einer
"`Enthalten-in"'- Hierarchie: Container in
Container in Container ...
- Hinzufügen einer Komponente zu einem Container:
add
- Festlegen des Layouts: Verschiedene Layoutmanager
- Handling von Events (Später)
Komponente |
Nutzen |
Component |
Wurzel der Containerhierarchie |
Button |
Knopf zum Klicken mit String als Beschriftung. |
Canvas |
Vanilla-Oberfläche |
Label |
eine Zeile read-only Text |
TextField |
Zeile edierbaren Text (s.a. TextComponent-Oberklasse) |
TextArea |
Mehrere Zeilen edierbaren Text |
List |
List selektierbarer Elemente |
Scrollbar |
wie der Name schon sagt; senkrecht oder waagrecht |
FileDialog |
Dialogbox zum Filebrowsen |
Checkbox |
An/Aus (s.a. CheckboxGroup. ``Checkbox/Radio buttons'') |
Choice |
Auswahlmenu (``Choice-Button'') |
Table 7: einige Komponenten (Unterklassen von Component)
Menu Component |
Nutzen |
Menu |
Pulldown Menu, in einer Menueleiste; add(_)
für Menuitems |
MenuBar |
Menuleiste. add(Menu m) fügt neue Menues hinzu |
MenuItem |
|
Container |
Nutzen |
Container |
Wurzel der Containerhierarchie |
Dialog |
Dialogboxen |
Window |
Top-level Fenster ohne sonstigen Schmuck (selten verwendet) |
Frame |
Fenster mit Rand (Unterklasse von Window) |
Panel |
Container innerhalb eines anderen, also nicht
stand-alone. Generischer Container ohne eigenes Verhalten,
hierarchisch schachtelbar, Oberklasse von Applet. |
ScrollPane |
einzelne Region mit zwei Scollbars, senkrecht und waagrecht |
-
spezielle Components zum Gruppieren von graph. Elementen
- zwei Arten von Containern
-
nur innerhalb anderer graphischer Container möglich:
Panel/Applet (z.B. innheralb des Appletviewers)
- die stand-alone laufen können/eine eigene graphische
Fläche im Fenstersystem bilden (siehe auch das Stand-Alone-Applet auf
Folie ??).
-
Layout Manager implementieren LayoutManager
interface51
- Wichtige Gruppe von Klassen im awt
- Verwendung: Instanzen werden als Argument der
Containermethode setLayout(..) gegeben.
- Neben dem default-Verhalten: keine Stategie (= null =
Layout ``per Hand'') gibt es vordefinierte Manager für
verschiedenen Strategien:
|
FlowLayout |
Fließtextartig |
GridLayout |
Spalten- und Zeilenanordnung |
BorderLayout |
N/S/O/W und einen in der Mitte |
CardLayout |
Nur eine Komponente zu einem Zeitpunkt |
GridBagLayout |
komlexere Strategie |
|
9 Events
Inhalt
Java 1.1 Ereignismodell ·ereignisgesteuerte Programme ·Vergleich von Events in 1.0 und 1.1 ·Listener-Interfaces ·Adapterklassen
Literatur:
Wir behandeln das Ereignismodell von Java 1.1. Wichtige Klassen finden
sich in java.awt.events und auch java.awt. Weitere
Information in Kapitel 7 von [Fla99b] sowie Kapitel
10 aus [LL97]. Wer bereits an Swing und dem
Event Modell in Java 1.2 interessiert ist, findet in
[Eck98] ein wenig Material, auch Diskussion der vielen
unterhaltsamen Unterschiede der AWTs in 1.0, 1.1 und 1.2.
-
GUI-Interaktion: ereignisgesteuert ÞKern der
Gui-programmierung: Events
- Eventmodell:52
"` Ereignisprotokoll"'. Unterschiedlich in
-
Java 1.0: einfach, plump, objekt-desorientiert, für größere
Oberflächen nicht geeignet, ``mißbilligt'' = deprecated
- Java 1.1: komplexer, baut auf innere
Klassen.53
- und nun:Java 1.2: Swing als GUI-Teil der
Java Foundation Classes (JVC)
- Nächstes Semester: wer weiß54
- Eventmodell: drei Mitspieler im Eventprotokoll
-
Event:
-
Instanz der Klasse java.util.EventObject, bzw. deren
Unterklasse java.awt.AWTEvent55
- Quelle (getSource)
- verschiedene ``Sorten'' von Events = verschiedene Unterklassen,
Event-Klassenhierarchie
- Definition eigener Eventklassen möglich
- neue Namenskonvention, Zusammenarbeit mit Java-Beans
- Varianten jeder Sorte als ``Feld-Konstanten''
- Quelle
-
generiert Events
- benachrichtigt die (passenenden) Listener durch
Methodenaufruf, Event als Parameter
- Unterhält eine Liste von Listenern, die
benachrichtigt sein wollen.
- erlaubt dynamische An/Abmeldung von Listener
- Beispiel für Ereignisquelle: java.awt.Container
- Listener
-
Empfänger der Ereignisse als Methodenparameter
- implementiert Listener-Interfaces
- für jede Klasse von Events: zugehöriges
Interface56
Figure 5: Event-Modell (AWT-Events)
Beispiel 22 [Alt und Neu]
Folgendes kleine Applet stellt die Eventmodelle von Java 1.0 und 1.1 im
Vergleich gegenüber. Man beachte die if-Kaskade im 1.0-Modell und die
Verwedung innerer Klassen für 1.1
import java.awt.*;
import java.awt.event.*; // Fuer Events
import java.applet.*;
public class AltundNeu extends Applet {
Button // Hier: 1.0 = 1.1
b1 = new Button("Knopf 1"),
b2 = new Button("Knopf 2"),
b3 = new Button("Knopf 3(alt)"),
b4 = new Button("Knopf 4(alt)");
public void init(){ // Applet-Methode
b1.addActionListener(new B1());
b2.addActionListener(new B2());
this.add(b1); add(b2); add(b3); add(b4);
};
// 1.1: zwei innere klassen B1 und B2
class B1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
getAppletContext().showStatus("Knopf 1");
};
};
class B2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
getAppletContext().showStatus("Knopf 2");
};
};
// -------------------- Java 1.0 -----------------
public boolean action(Event evt, Object arg) {
if (evt.target.equals(b3))
getAppletContext().showStatus("Knopf 3");
else if (evt.target.equals(b4))
getAppletContext().showStatus("Knopf 4");
else return super.action(evt, arg);
return true; // true als Erfolgsmeldung
};
};
-
zu jeder Sorte Event: ein entsprechendes Interface
- Interface muß durch den Listener imlementiert werden
Þ zwei Alternativen:57
-
direkte Implementierung des Interfaces mit
implements
- indirekt mittels Adapter-Klasse
-
Adapter-Klasse: triviale (nicht
abstrakte) Implementierung des zugehörigen Interfaces
- Listener: durch Unterklassenbildung und
Überschreiben der benötigten Methoden
Eventklassen und Listenerklassen
|
-
Namenskonvention:
s. Table 8
- Beispiel 22 auf
Folie ??: Sorte = Action
-
Quelle = Button erzeugt Instanzen von
ActionEvent.1
- innere Klasse B1 implementiert das
Interface ActionEventListener.
- Dies Interface listet auf, auf welche Methoden ein
ActionListener horchen muß ÞactionPerformed enthält
den programmspezifischen Kode
- Registrierung des Listeners new B1()an der
Quelle: b2.addActionListener(new B1());
SorteEvent |
SorteListener |
SorteAdapter |
addSorteListener |
removeSorteListener |
|
Zu jeder Sorte (siehe nächste Folie) gibt es eine
Klasse der Events und ein Interface der zugehörigen Listener
sowie den Adapter. Daneben die Methoden in den Quellen zum
An/Abmelder der Listener. Ausname: Sorte =
Mouse (MouseListener und
MouseMotionListener) |
|
Table 8: Eventklassen (Übersicht)
Sorte |
Methoden |
Quelle (nur die höchsten in der Hierarchie aufgelistet) |
Action |
actionPerformed |
Button List TextField MenueItem |
Adjustment |
adjustmentValueChanged |
Scrollbar |
Container |
componentAdded componentRemoved |
Container |
Component |
componentMoved componentHidden
componentResized componentShown |
Component |
Focus |
focusGained, focusLost |
Component |
Item |
itemStateChanged |
Checkbox, CheckboxMenuItem, Choice, List |
Key |
keyPressed keyReleased
keyTyped |
Component |
Mouse |
mouseClicked
mouseEntered
mouseExited
mousePressed
mouseReleased |
|
mouseDragged MouseMoved |
|
Component |
Text |
textValueChanged |
TextComponent |
Window |
windowOpened WindowClosing
windowActivated
windowClosed
windowDeactivated
windowDeiconifed
windowIconified |
Window |
Table 9: Eventklassen
15. Mai
10 Threads
Inhalt
Threads ·Zustände von Threads ·Synchronisation ·Prioritäten ·Threadgroups
Literatur:
[Fla99b] gibt diesmal nicht soviel her, zumindest
nicht auf einem Fleck konzentriert. In [LL97] werden
Threads in Abschnitt 14.2 besprochen. Der entsprechende Abschnitt in Suns
Javatutorial [CW96] ist ebenfalls recht
brauchbar. Daneben gibt es natürlich noch [OW97]
nur über Threads in Java, aber ich kenne es nicht selbst. Auch in
[Lea99] findet sich eine sehr empfehlenswerte Beschreibung
von Synchronisation in Java, auch in einem größeren Kontext
(insbesondere Abschnitt 2.2 für Locking). In der Klassenbibliothek sind
java.lang.Thread und java.lang.ThreadGroup die
wichtigsten Klassen zum Thema.
- Definition:
Thread: ein sequentieller Kontrollfluß
innerhalb eines Programmes
|
- bezeichnet auch als lightweight processes
- quasi-parallele Ausführung mehrerer sequentieller
Kontrollfüsse ( Multi-Threaded)
- Bisher: Ein (Anwender)-Programm/Applet = ein Thread (single
threaded), aber:
- im Laufzeitsystem: Threads, die von der Java
Virtual Machine automatisch erzeugt und verwaltet werden:
Dämonen
-
Garbage Collection: niederpriorer Hintergrundthread
- Threads für das Event-Handling
- ein Thread bedient die main-Methode
- Programmterminierung: alle nicht-Dämonenthreads sind beendet
- Thread: Verwaltung von threads: starten, stoppen,
Prioritäten setzen ...
- Thread kann eine best. Priorität haben
-
Klasse java.lang.Thread, muß also nicht importiert werden
- Thread implementiert Runnable
- zwei Arten, Threads zu generieren:
t]15cm
-
als Unterklasse der Thread-Klasse und
überschreiben der run-Methode, oder
- Implementierung des Runnable-Interface.
|
- run() ist der Rumpf der Threads
- Der Thread-Konstruktor nimmt die Implementierung des
runnable-Objektes als Argument58
- Ein neuer Thread wird | wie üblich | mit new erzeugt und
durch Aufruf von start gestarted.
- Thread endet, wenn das Ende der
run-Methode erreicht wird.
- Mit suspend und resume kann die Verarbeitung eines threads
angehalten/fortgesetzt werden.
Beispiel 23 [ Unterklasse von Thread]
Die Klasse erweitert einfach Threads und überschreibt
die run-Methode.
public class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() { // "uberschreiben
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
};
Beispiel 24 [ Implementieren von Runnable]
Dies ist die zweite Möglichkeit, wie man einen Thread bekommen kann.
Der Konstruktor der Thread-Klasse macht aus einem
Objekt, das ein Runnable-Interface implementiert, den
eigentlichen Thread. Dieser muß dann extra gestartet werden.
Das starten wiederum ruft run auf.
import java.awt.Graphics;
import java.util.*;
import java.text.DateFormat;
import java.applet.Applet;
public class Clock extends Applet implements Runnable {
private Thread clockThread = null;
public void start() {
if (clockThread == null) {
clockThread = new Thread(this, "Clock"); // Konstuktor Thread
clockThread.start();
}
}
public void run() { // wg. Interface runnable
Thread myThread = Thread.currentThread();
while (clockThread == myThread) {
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e){}
}
}
public void paint(Graphics g) {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
DateFormat dateFormatter = DateFormat.getTimeInstance();
g.drawString(dateFormatter.format(date), 5, 10);
}
public void stop() { // Applets stop Methode
clockThread = null;
}
};
-
neu: bereits instantiiert, aber noch nicht gestartet
- ausführbar
- tot: am Ende der run-Methode. Oder auch nach
Aufruf von stop, wird aber in Java-1.2 missbilligt
- blockiert/nicht ausführbar. Mehrere Gründe
-
schlafend: feste Zeitspanne
- suspendiert: keine Reaktion bis resume von
außen aufgerufen wird
- wartend: keine Reaktion bis notify
- Aufruf einer synchronisierten Methode an einem Objekt,
welches gerade anderweitig beschäftigt (locked) ist
- Warten auf Beendigung von I/O, beispielsweise ein
Strom
Lebenszyklus eines Threads
|
Hier eine Zusammenfassung der Zustände und Übergänge von
Threads:
-
Quasi-paralleler Zugriff auf gemeinsame Daten Þ
notwendig
- Kritischer Abschnitt: Programmabschnitt, für den
gegenseitiger Ausschluß (also exklusiver Zugriff) erforderlich
ist.
Beispiel 25 [Leser/Schreiber]
In folgendem Scenario haben die Objekte Schreiber und Leser Zugriff auf
dasselbe Speicherobjekt, der eine schreibend, der andere lesend. Das
Speicherobjekt soll einfach eine Speicherzelle darstellen, auf
die mit den Methoden get und put zugegriffen wird.
Es gibt zwei Dinge zu koordinieren:
-
gegenseitiger Ausschluss: locking
- Unterschiedliche Geschwindigkeiten von Leser und Schreiber
( race conditions): der Zugriff muss abgestimmt werden.
Gegenseitiger Ausschluss (synchronized)
|
Beispiel 26 [Leser/Schreiber (2)]
Da im Leser/Schreiber-Beispiel mittels der beiden
Zugriffsmethoden get und put auf die
gemeinsamen Daten zugegriffen werden soll, kann man den gleichzeitigen
Zugriff dadurch verbieten, dass man die Methoden als
synchronized markiert.
public class Speicher { // Speicher muß kein Thread sein
private int speicherzelle // das gemeinsame Datum
public synchronized int get () {
....
};
public synchronized void put (int value) {
....
};
};
-
nicht nur Verhindern von gleichzeitigem Zugriff, sondern auch
explizites
-
Warten auf das Eintreten von Ereignissen (genauer eine
Benachrichtigung) und
- Benachrichtigen von deren Eintreten
notwendig
- Instanzmethoden in java.lang.Object
-
wait: Warten auf Benachrichtigung
- drei Formen, zwei mit Timeout
-
wait()
- wait (long timeout)
- wait (long timeout, int nanoseconds)
- notify: Benachrichtigung einer bestimmten Instanz
- notifyAll: alle benachrichtigen
- Vorsicht vor Deadlocks durch zyklisches
Warten.
- Die erwähnten Methoden sind nur innerhalb von
synchronisierten Blocks oder Methoden erlaubt.
- wichtiger Unterschied zu
suspend/ resume: Im Wartezustand
gibt der Thread den Lock frei.
Beispiel 27 [Leser/Schreiber (3)]
In dem Leser/Schreiber-Beispiel kann man diese Methoden verwenden, um die
Geschwindigkeit der Threads anzugleichen.
public synchronized int get() {
while (available == false) { // Explizite Schleife
try {
wait(); // Warten auf den Schreiber
} catch (InterruptedException e) {
}
}
available = false;
notifyAll(); // Benachrichtigen
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait(); // Warten auf den Leser
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll(); // Benachrichtigen
}
Sonstige Interaktion mit Threads
|
-
sleep(long milliseconds)
-
für festgelegte Zeitspanne deaktivieren/pausieren
- Klassenmethode der Klasse Thread
- Verwendung oft einfach Thread.sleep(100)
- join(): Instanzmethode, warten auf den Tod
eines Threads
- Mißbilligte Methoden (ab Java 1.2
deprecated)
-
suspend/resume: zweitweises Anhalten und
Weitermachen
-
ein suspendiertes Objekt gibt (anders als ein wartendes)
seine Locks nicht frei Þ
- führt leicht zu Verklemmungen
- stop: Abbrechen
-
gibt alle Locks frei Þ
- Gefahr von inkonsistentem Zustand
- wirft eine Ausnahme,
und zwar eine Unterklasse von Error Þfehlerhafter Abbruch
- interrupt: unterbrechen
- destroy: wurde (noch) nie implementiert, ein
suspend ohne resume.60
Alternative zum Suspendieren
|
Beispiel 28 [Suspendieren]
Folgendes Beispiel zeigt, wie man die Methoden suspend und
resume umgehen kann, indem man wait und notify
und ein Flag (hier suspended verwendet. An Stelle
von suspend und resume treten Methoden
mySuspend und myResume. Das Flag schaltet den
suspend-Zustand ein und aus. Das wait muß
synchronisiert sein.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Suspend extends Applet {
private TextField t = new TextField(10); // output
private Button // zwei Kn"opfe
suspendbutton = new Button("Suspend"),
resumebutton = new Button("Resume");
public class Suspendable extends Thread {
private int count =0;
private boolean suspended = false; // Flag
public Suspendable (){ start();};
public void mySuspend() {
suspended = true; // Flag => true
};
public synchronized void myResume(){
suspended = false; // Flag => false
notify();
};
public void run() { // Runnable
while (true) {
try {
sleep(100);
synchronized(this) { // auf sich selbst
while (suspended) wait(); // sync-Block
}
} catch (InterruptedException e){};
t.setText(Integer.toString(count++));
};
};
};
private Suspendable ss = new Suspendable();
public void init() { // Applet
add(t);
suspendbutton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
ss.mySuspend();
}
});
resumebutton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
ss.myResume();
}
});
add(suspendbutton); // Kn"opfe ans
add(resumebutton); // Applet heften
}; // Ende init
public static void main(String[] args) { // stand-alone
Suspend applet = new Suspend();
Frame aFrame = new Frame("Suspend");
aFrame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0); // ordentlich
}; // terminieren
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300, 300);
applet.init();
applet.start(); // thread starten
aFrame.setVisible(true); // = show
};
};
-
quasi-parallele Ausführung von mehreren Threads Þ Scheduler
- Javas Laufzeitsystem: Scheduling mit fester
Priorität61 (fixed priority scheduling)
-
mehrere Threads ausführbar: nimm den
dringlichsten62
- unterbrechend: es läuft immer63 der ausführbare Thread mit der
höchsten Priorität, solange bis er
-
endet64
- ein Ergebnis liefert (yield) oder sonstwie
- nicht-laufend (non-runnable) wird
- ein dringlicherer Thread ausführbar wird.
- Bei Gleichstand: zyklische, nicht-interbreachende
Auswahl. (round robin)
- Manche Betriebssysteme (nicht Javas Laufzeitsystem)
erzwingen Time-slicing, aber: nicht darauf verlassen
(Platformunabhängigkeit)
- Thread erbt die Priorität seines Erzeugers
- Verändern der Priorität: setPriority, Lesen
mit getPriority
- Verhindern von Aushungern:
-
yield: statische Methode: Thread gibt
die Kontrolle auf, lässt anderen gleichprioren Thread den
Vortritt
-
Klasse java.lang. ThreadGroup.
- Jeder Thread gehört zu einer Gruppe (notfalls der
System-Defaultgruppe)
- Gruppen von zusammengehörenden Threads
- statische Gruppenzugehörigkeit
- Operationen auf der Gruppe als Ganzem
-
Informationen über alle Threads der Gruppe sammeln
- Gruppe selbst hat Attribute (z.B. maximale Priorität)
- Interaktion mit allen Threads der Gruppe auf einmal
(alle auf einmal starten etc.)
- Zugriffsbeschränkungen, basierend auf
Gruppenzugehörigkeit (SecurityManager)
- Hierarchie von Thread-Gruppen
?
11 Networking
Inhalt
Internetadressierung ·Sockets und Ports ·Client/Server-Programmierung ·Multicasting ·höhere
Netzdienste
Literatur:
Das relevante API Paket ist java.net; für remote method
invocation java.rmi.*. Material und Beispiele zum Thema
findet sich in Kapitel 9 von [Fla97a] sowie
in Kapitel 15 von [Eck98]. Auch der entsprechende
Abschnitt aus dem Tutorial [CW96] ist als
Einstieg brauchbar. Darüberhinaus gibt es noch
[Har97] nur über Netzwerkprogrammierung,
aber ich kenne es selbst nicht. Ein wenig über die verschiedenen
Internetprotokolle habe ich aus [Tan96].
-
IP-Adressen: Adressierungschema des
Internet-Protokolls, momentan (IPv4) 32 Bit
-
in dezimaler Punkt-Schreibweise 134.245.253.7
- DNS-Namen: garfield.informatik.uni-kiel.de
- Spezialadressen, z.B. 127.xx.yy.zz: Loopback,
gut zum Testen
- Port
-
TCP-Schichten Modell
- Transport Layer Service Access Point (ISO-Schicht 4), d.h., dort
stehen Transportschicht-Dienste zur Verfügung
- 16-bit Port Nummer. £ 256: ``wohlbekannte``
Ports65, bis
1024 reserviert.
Beispiel 29 [Adresse]
Mittels statischer
Methoden der Klasse InetAddress kann
man die TCP/IP-DNS-Adreßdienste nutzen. Instanzen von
InetAddress sind IP-Adressen (allerdings hat die Klasse keinen
Konstruktor, verwendet für Sockets, ...).
import java.net.*;
public class NSLookup { // einfache DNS-Anfrage
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: NSLookup machine");
System.exit(0); //
};
InetAddress la = InetAddress.getLocalHost();
InetAddress a = InetAddress.getByName(args[0]);
System.out.println(a);
System.out.println("Lokaler Host: " + la);
};
};
-
Sockets: Endpunkte einer Transportverbindung
- dienen zur Interprozeßkommunikation
- Adressierung der Sockets:
Socket = IP-Adresse × Port-Nummer
|
d.h., Socket = Transportschichtadresse, in Java als Instanzen der Klasse
java.net.Socket
- mehrere Verbindungen über den selben Port/Socket möglich
- zurückgegeben von ServerSocket.accept
- zwei Transportprotokolle:66, beide Ende-zu-Ende-Protokolle, beide
voll-duplex
-
Verbindungsorientiert: TCP
-
fehlergesichert
- reihenfolgegesichert ÞByte strom
- Klasse Socket
- verbindungslos: UDP
-
Datagram-Dienst
- Datagramme als Instanzen von DatagramPacket
- Klasse DatagramSocket
-
Server stellt Dienste zur Verfügung; im OO-Modell:
Methoden
- Klienten fordern Dienste an; im OO-Modell:
Methodenaufruf
Beispiel 30 [Server]
Ein einfacher statischer
Server, der einen Socket
aufmacht und zeilenweise Zeichen liest.
import java.io.*;
import java.net.*;
public class Server {
public static final int PORT = 2000; // Portnummer
public static void main (String[] args) throws IOException {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Started: " + s);
try {
Socket socket = s.accept(); // Beginn der Bereitschaft
try {
System.out.println("Connection accepted:" + socket);
BufferedReader in =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true); // autoflush=on for println
while (true) { // Lesen bis "END"
String str = in.readLine(); // zeilenweises Lesen
if (str.equals("END")) break; // Abbruch
System.out.println("Echoing: " + str); // R"uckkanal
out.println("Echoing: " + str); // Echo -> stdout
}; }
finally {
System.out.println("closing ..");
socket.close();
}}
finally {s.close();}};
};
Beispiel 31 [Client]
Hier der zu dem Server aus Beispiel 30 auf
Folie ?? passende Klient.
import java.net.*;
import java.io.*;
public class SingleClient {
public static void main (String[] args) throws IOException {
InetAddress addr = InetAddress.getByName(null); // null = local host
System.out.println("addr = " + addr);
Socket socket = new Socket (addr, SingleServer.PORT);
try {
System.out.println("socket = " + socket);
BufferedReader in =
new BufferedReader(
new InputStreamReader (socket.getInputStream()));
PrintWriter out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
for (int i = 0; i< 10; i++){
out.println("Hello World" + i);
String str = in.readLine();
System.out.println(str);
};
out.println("END");
} finally {
System.out.println("closing...");
socket.close();
}
};
};
-
in der Regel: ein Server für dynamische Anzahl von
Klienten
- Server aus Beispiel 30 kann nur
einen Klienten gleichzeitig bedienen
- Þ Threads
-
der Multi-Server behält den vereinbarten Port im Auge
- sobald neue Anfrage: Erzeugung (``spawn'') eines neuen
Server-Threads
- Socket als Konstruktor- Parameter
Beispiel 32 [Server]
Hier der entsprechende Code.
import java.io.*;
import java.net.*;
public class MultiServer { // Startet die Unterthreads
public static final int PORT = 2000;
public static void main(String[] args)
throws IOException {
ServerSocket s = new ServerSocket(PORT); // Zum Horchen
System.out.println("Started: " + s);
try {
while (true) { // Soviele wie verlangt
Socket socket = s.accept();
try {
new ServeOne(socket); // socket als Param.
} catch (IOException e) {
socket.close();
};
};
}
finally {s.close();};
};
};
Beispiel 33 [Server]
Hier ein einzelner Serverprozeß. Er bekommt den Socket den
er bedienen soll, als Parameter. Ansonsten analog zum Server aus
Beispiel 30.
import java.io.*;
import java.net.*;
public class ServeOne extends Thread {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ServeOne (Socket s) throws IOException {
// Socket als Parameter
socket = s;
BufferedReader in = // genau vor vorher
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = // ganau wie vorher
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
start(); // ruft run() auf
};
public void run () { // "Uberschreiben der run-Methode
try {
while (true) { // Loop
String str = in.readLine();
if (str.equals("END")) break;
System.out.println("Echoing: " + str);
out.println(str);
};
System.out.println("closing ..");
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException e) {}
};
};
};
Beispiel 34 [Klienten]
Der Vollständigkeit halber noch das selbe für Klientenseite.
Hier der Prozeß, der alle Klienten erzeugt:
import java.net.*;
import java.io.*;
public class ManyClients {
static final int MAX_THREADS = 4;
public static void main(String[] args)
throws IOException, InterruptedException {
InetAddress addr = InetAddress.getByName(null); //
while (true) {
if (OneClient.threadCount() < MAX_THREADS)
new OneClient(addr);
Thread.currentThread().sleep(1000);
};
};
};
Beispiel 35 [Ein Klient]
Schließlich ein einzelner Klient, der Code ist nicht wesentlich anders
als zuvor:
import java.net.*;
import java.io.*;
public class OneClient extends Thread{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private static int counter = 0;
private int id = counter++;
private static int threadcount = 0;
public static int threadCount() {
return threadcount;
};
public OneClient(InetAddress addr) {
System.out.println("Neuer Klient @ " + id);
threadcount++;
try {
socket = new Socket(addr, MultiServer.PORT); //stat. Adresse
} catch (IOException e) {}
try {
in =
new BufferedReader(
new InputStreamReader (socket.getInputStream()));
out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
start(); // starte Thread -> run
} catch (IOException e) {
try {
socket.close();
} catch (IOException e2) {}
};
};
public void run() {
try{
for (int i = 0; i< 25; i++){
out.println("Client" + id + ": " + i );
String str = in.readLine();
System.out.println(str);
};
out.println("END");
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException e) {}
threadcount--;
};
};
};
e
-
funktioniert ähnlich wie ServerSockets nur mit
DatagrammSocket
- basierend auf UDP
- Klasse DatagrammPacket: Instanzen sind, klar,
Datagramme, also UDP-SDUs
- zwei Konstruktoren: zum Empfangen und zum Senden
DatagramPacket(buf, buf.length) // R
DatagramPacket(buf, buf.length, inetAddress, port) // S
- Gesendet werden: Arrays von Bytes (Maximum < 64KByte)
- verbindungsloser Dienst Þkeine Analogie zu
ServerSocket.accept()
- Codefragmente:
- Spezialfall: Multicasting
-
URL: Uniform recource allocator
- eindeutige Adressierung von Netzresourcen (oft
HTML-Seiten oder Code):
- Format von URLs. Die Adresse wird meist als DNS-Name
angegeben. Bei dem Dateipfad steht ein / am Ende für die
Standarddatei index.html.
Bestandteil |
Methoden |
Protokoll/Scheme |
|
getProtocol |
Resource-Adresse |
Host-IP-Adresse |
getHost |
|
Datei (inkl. Pfad) |
getFile |
|
Portnummer (opt.) |
getPort |
|
Referenz (opt.) |
getRef |
- URL's als Java- Objekte. Beispiel:70
String hostname = "www.informatik.uni-kiel.de";
String protocol = "http";
String filename = "/inf/deRoever/SS00/Java/"; // = index.html
URL kursurl = new URL(protocol,
hostname,
filename);
- relative Urls in Java: mittels des überladenen
Url-Konstruktors:
URL (URL baseURL, String relativeURL)
Zum Beispiel:
URL gruppenitem_url = new URL(kursurl, "#gruppen");
URL gruppen_url = new URL(kursurl, "gruppen.html");
- Instanzen von URL sind unveränderliche Objekte,
d.h., es gibt keine Methoden setFile etc.
Protokoll |
Verwendung |
Beispiel |
http |
Hypertext (HTML) |
http://www.informatik.uni-kiel.de/~ms |
ftp |
File transfer |
ftp://ftp.informatik.uni-kiel.de/pub/kiel/ |
file |
lokale Datei |
/home/ms/.plan |
news |
Brett/Artikel |
news:cau.ifi.fragen |
news:AA4534345@news.informatik.uni-kiel.de |
|
gopher |
Gopher |
gopher://gopher.informatik.tu-muenchen.de/ |
mailto |
Email |
mailto:ms@informatik.uni-kiel.de |
telnet |
Einloggen |
telnet://snoopy.informatik.uni-kiel.de:80 |
Table 10: Verschiedene URL's
-
Kommunikation mittels Url: öffnen und
schließen passender Ströme71
-
Methode |
Rückgabetyp |
Nutzen |
openConnection() |
UrlConnection |
zum Lesen und Schreiben von und auf die
UrlConnection. |
openStream() |
InputStream |
erlaubt das direkte Lesen von einem Url, |
- Verbindungen auf Anwendungsschicht über Urls
-
Instanzen von UrlConnection
- Ergebnis von openConnection(), kein
Konstruktor72
- Erlaubt mehr Kontrolle über die Verbindung also die
openStream-Methode eines Url-Objektes
- Lesen und Schreiben möglich, aber default: nur Lesen.
Manipulation mit setDoInput und setDoOutput
- eine Reihe weiterer Methoden, bitte selber nachschlagen
12 Verteilte Objekte (RMI)
Inhalt
Literatur:
Eine Einführung findet sich im Nutshellbuch
[FFCM99] über Javas sogenannte
Enterprise-Klassen (Kapitel 3, 8 und 13). Einiges ist
anscheinend auch in [Har97] enthalten.
Schließlich noch [Lea99].
Remote Method Invocation: Einleitung
|
-
bisher: richtig verteilte Berechnungen Anwendungen | bis auf
das low-Level Client/Server-Modell | haben wir noch nicht kennengelernt,
nur
-
verteilten Code (distributed code) ¹
verteilte Programmierung mittels Applets
- (hauptsächlich) Lesen verteilter Daten durch das Laden
von File-Urls
- quasi-parallele Ausführung durch mehrere Threads
- echte Verteilung:
Methodenaufruf an Objekten auf anderen Maschinen
|
- Pakete (³ Java 1.1)
java.rmi |
Remote interface und Exception |
java.rmi.server |
u.a. remote Objects |
java.rmi.dgc |
Distributed GC |
java.rmi.registry |
Verwaltung von RO's |
- gehört zu den
Enterprise-Klassen.73
-
im Folgenden: Server: (Java)programm, welches Methoden
über's Netz anbietet, Klienten sind die Aufrufer
- ein klein wenig wie die Client/Server auf den Sockets, aber
- wichtigste neue Zutat: Aufruf von Methoden an Objekten mit ihrem
Namen anstelle von Kommunikation mit Ports!
- Bestandteile:
-
Remote Interface: legt die von Ferne zugreifbaren
Methoden fest: Subinterface von rmi.Remote
- Server: implementiert das Interface
- Nameservice: eigenes Programm/Dämon rmiregistry
- Klient: erkundigt sich beim Nameservice nach den
Servern
Figure 6: Remote method invocation
-
remote interface
-
Erweiterungen des (leeren) Interface
java.rmi.Remote74 Þnur die Methoden die in einem remote
Interface spezifiziert sind, sind auch von Ferne zugreifbar.
- alle Methoden des Interfaces: throws
RemoteException notwendig
- die Schnittstelle muß public sein
- die Remote Objects: deklariert als Implementierungen
der remote interfaces (nicht ihrer
Implementierungsklasse!)75
- Implementierung eines RI:
-
Klasse, deren Instanzen die verteilten Methoden zur Verfügung
stellen
- (meist) Erweiterungen von
UnicastRemoteObject
- (Sicherheitsregistratur java.rmi.RMISecurityManager)
Registration von Remote-Objekten
|
Programmstummel (Stubs) und Skelette
|
Verwenden einen RO: Klienten
|
19. Juni 2000
13 Datenbankanbindung mit JDBC
Inhalt
Einführung ·Structured Query Language ·Relationale Datenbanen
Literatur:
Die API zur Datenbankanbindung and SQL-Datenbanken gehört zu den
sogenannten Enterprise-Klassen, Material findet sich entsprechend
in [FFCM99] (Kapitel 2 und Kapitel 18,
eine SQL-Superkurzeinführung in Kapitel 8).
Ein fettes Buch zum Thema ist [WFC+99] (da zugehörige
online-Material
enthält auch ein kleines Tutorial.) Ein Datenbankbeispiel findet sich
auch in [Fla97a] (Kapitel 16)
Wir können hier nur sehr oberflächlich auf SQL eingehen, auf der
Webseite unseres Kurses sind ein paar weiterführende Informationen
aufgelistet.
-
JDBC: Teil der sogenannter
Enterprise-Klassen von Java78
- dient zum Arbeiten mit relationaler Datenbanken
- Java-Pakete: java.sql + Erweiterung javax.sql
- Interaktion mittels SQL-Anfragen79
- Unabhängig vom Datenbanksystem: Anpassung durch
entsprechende Treiber
- Grundschritte jeder Datenbankbenutzung (siehe Beispiel
auf Seite ?? (Vorraussetzung: Datenbank
läuft bereits)
-
Laden des Treibers
- Erzeugen einer Verbindung
- Erzeugen eines Datenbank- Befehls (Statement)
- Ausführen einer SQL-Anfrage
- Sammeln und Auswerten der Resultate
- Schließen der Resourcen
- Bei mehreren Befehlen: Schritte 3+4+5 müssen wiederholt werden
(nicht nur 4 und 5)
-
Kapselung/Abstraktion der Datenbankimplementierung
- Java-Objekt
- Benuztung: Registrierung beim Manager
- 4 Arten von Treibern
-
JDBC-ODBC-Bridge
- Native-API- Partly Java
- All Java
- Native protocol All-Java
- Sammlung von
Treibern
- bei uns Postgres-Datenbank mit
Typ-3-Treiber
-
Statement: zum Ausführen von
Datenbankbefehlen
- Interface java.sql.Statement
- erzeugt mittels createStatement() einer
Connection
Statement stmt = con.createStatement();
|
- eigentliches SQL-Statement in Java:
-
Code |
Anfrage |
Beispiel |
stmt.executeQuery(``SQL''); |
lesend |
SELECT |
stmt.executeUpdate(``SQL''); |
schreibend |
UPDATE, DELETE |
stmt.execute (``SQL'') |
stmt.getResultSet () |
|
versuchsweise |
- ein Statementobject = Ein Anfrage
- nach Gebrauch: schließen80
-
konzeptionell in einer Tabelle (Zeilen/Spalten)
aufgebaut entsprechend der gestellten Anfrage
- Objekt vom Interface ResultSet kapselt die Tabelle
- Zugriff:
-
Zeile
-
sequentiell Zeile für Zeile,
- Methode next() der Tabelle
- initial: vor der ersten Zeile
- nachgeordnet: Spalte
-
wahlfreier Zugriff
- (viele) Methoden, je nach Typ
- insbesondere getString(), getXXX() über Name
der Spalte (d.h. String-Argument) oder Index
(int-Argument von 1 bis n).
- allgemeinster Fall: getObject()
import java.sql.*;
public class JDBCSample {
public static void main(java.lang.String[] args) {
try {// This is where we load the driver
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch (ClassNotFoundException e) {
System.out.println("Unable to load Driver Class");
return;
}
try {// access is within a try/catch block.
Connection con =
DriverManager.getConnection("jdbc:odbc:companydb", "", "");
Statement stmt = con.createStatement(); // Create/execute statement
ResultSet rs = stmt.executeQuery("SELECT FIRST_NAME FROM EMPLOYEES");
while(rs.next()) { // Display the SQL results.
System.out.println(rs.getString("FIRST_NAME"));
}
rs.close(); stmt.close(); con.close(); // Freigeben der Rescourcen
}
catch (SQLException se) {
// Inform user of any SQL errors
System.out.println("SQL Exception: " + se.getMessage());
se.printStackTrace(System.out);
}
}
}
-
SQL-pakete importieren: import java.sql.*;
- postgres- Treiber einbinden:
try {
Class.forName("org.postgresql.Driver");
} catch(java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
- Verbindung zur Datenbank `JavaUeb' herstellen:
String url = "jdbc:postgresql://sokrates/JavaUeb";
Connection con;
con = DriverManager.getConnection(url, "postgres", "");
- Nach getaner Arbeit die Verbindung schließen:
con.close();
SQL + relationale Datenbanken
|
Datentypen: JDBC ® Javatypen
|
JDBC Type |
Java |
ARRAY |
Array |
BIGINT |
long |
BINARY |
byte[] |
BIT |
boolean |
BLOB |
Blob |
CHAR |
String |
CLOB |
Clob |
DATE |
java.sql.Date |
DECIMAL |
java.math.BigDecimal |
DISTINCT |
mapping of underlying type |
DOUBLE |
double |
FLOAT |
double |
INTEGER |
int |
JAVA_OBJECT |
underlying Java-Class |
LONGVARBINARY |
byte[] |
LONGVARCHAR |
Strirg |
NULL |
? |
NUMERIC |
java.math.BigDecimal |
OTHER |
? |
REAL |
float |
REF |
Ref |
SMALLINT |
short |
STRUCT |
Struct |
TIME |
java.sql.Time |
TIMESTAMP |
java.sql.Timestamp |
TINYINT |
byte |
VARBINARY |
byte[] |
VARCHAR |
String |
Schemamanipulation: Erzeugen
|
-
Wichtigste Schemanmanipulation: Erzeugen einer
Tabelle: CREATE
- weitere: Verändern/Löschen (ALTER, DROP ...)
CREATE [ [ GLOBAL | LOCAL ] TEMPORARY]
TABLE <table_name>
( { <column_name> { <data_type> | <domain_name>}
[<column_size>]
[<column_constraint>] ...}
[DEFAULT <default_value], ..
[<table_constraint>], ...
[ ON COMMIT { DELETE | PRESERVE} ROWS ] )
-
Beispiel
CREATE TABLE COFFEES
(COF_NAME VARCHAR(32),
SUP_ID INTEGER,
PRICE FLOAT,
SALES INTEGER,
TOTAL INTEGER)
- Constraints: Standartbedingungen, per
Spalte oder per Tabelle
Spaltenconstraints (können
kombiniert werden) |
PRIMARY KEY |
Hauptspalte (für 0 oder 1 Spalte, keine doppelten Einträge) |
NOT NULL |
leerer Eintrag verboten |
UNIQUE |
Doppeleinträge verboten |
Tabellenconstraints |
UNIQUE |
keine Doppeleinträge, kann auch für
Teilmenge der Spalten definiert sein
(UNIQUE(<spalte_a>,...)) |
PRIMARY KEY |
Kombination mehrerer Spalten erlaubt! |
-
bei existierender Tabelle: Anfragen und Manipulation
einzelner Daten.
- im Wesentlichen:
-
Lesen: SELECT
- Erzeugen: INSERT
- Überschreiben: UPDATE
- von Einträgen pro Tabelle
-
Lesen mittel SELECT
- Komplexer SQL-Befehle, hier nur beipielhaft
-
SQL-code |
Erklärung |
SELECT * FROM BOOKS |
alle Spalten |
SELECT * FROM BOOKS ORDER BY
TITLE |
Sortieren |
SELECT TITLE,AUTHOR FROM BOOKS |
Teilmenge der Spalten |
SELECT * FROM BOOKS WHERE PRICE <
10.0 |
nach Prädikaten |
SELECT * FROM BOOKS WHERE PRICE <
10.0 OR EDITION = 1 |
log. Verknüpfung |
SELECT * FROM PERSONS WHERE TITLE
LIKE'%Java%' |
partieller Stringmatch |
SELECT * FROM BOOKS WHERE PRICE
IN (3.99, 4.99, 5.99) |
enthalten in expliz. Aufzählung |
SELECT * FROM BOOKS WHERE PRICE
IN SELECT PRICE FROM PRICES |
Schachtelung ( Subquery) |
- atomare Prädikate:82
=,<.>,<=,!=,<>, LIKE, IS NULL, IN, BETWEEN
- wichtig Stringmatch mit =, Unterscheidung
Groß/Kleinschreibung
- Matching von Teilen mit LIKE
-
_ höchstens ein Zeichen
- % beliebig viele Zeichen
Subqueries, Joins, Groups
|
-
Subqueries: geschachteltes
SELECT/IN.
- Join Anfragen an mehr als eine Tabelle
-
Restriktion des Outputs gemäß der Relation der
Tabellen
- zwei Arten:
-
equi-join/Innerer Join
-
symmetrisch
- gemeinsame Spalte in zwei Tabellen
- Dot-Syntax oder
JOIN- ON-Schlüsselwort
- Default-join = innerer Join
- äußerer Join
-
asymmetrisch
- zwei Arten: linker und rechter
äußerer Join (je nachdem, wo der Primärschlüssel
enthalten ist.
- LEFT JOIN/ RIGHT
JOIN
SQL-code |
Erkärung |
SELECT * FROM BOOKS WHERE PRICE
IN SELECT PRICE FROM PRICES |
Schachtelung in einer Tabelle |
SELECT * FROM CUSTOMERS, ORDERS WHERE
ORDERS.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID |
equi-join, Dot-Syntax |
SELECT * FROM CUSTOMERS INNER JOIN ORDERS
ON ORDERS.CUSTOMER_ID =
CUSTOMERS.CUSTOMER_ID |
equi-join,
JOIN-ON-Syntax |
SELECT * FRROM CUSTOMERS LEFT JOIN ORDERS
ON CUSTOMERS.CUSTOMER_ID =
ORDERS.CUSTOMER_ID |
Äußerer Join, Primärschlüssel in Tabelle
CUSTOMERS |
-
Ein paar nützliche Hilfs funktionen:
-
COUNT(*)
- Pro Spalte: AVG, SUM, MAX,
MIN
- CURRENT_DATE/CURRENT_TIMESTAMP: nützlich zum
Vergleich mit Datumseinträgen
- Stringconcatenation: ||
- Stringkonversion: UPPER,
LOWER
- TRIM: Abschneiden von Zeichen am
Anfang/ Ende einer Zeichenkette
- SUBSTRING: Teilzeichenkette
References
- [Bud97]
-
Timothy Budd.
An Introduction to Object-Oriented Programming.
Addison-Wesley, 2 edition, 1997.
- [CW96]
-
Mary Campione and Kathy Walrath.
The Java Tutorial.
The Java series. Addison-Wesley, 1996.
- [Eck98]
-
Bruce Eckel.
Thinking in Java.
Prentice Hall, 1998.
- [FFCM99]
-
David Flanagan, Jim Farley, William Crawford, and Kris Magnusson.
Java Enterprise in a Nutshell.
O'Reilly, 1 edition, September 1999.
- [Fla97a]
-
David Flanagan.
Java Examples in a Nutshell.
O'Reilly, 1 edition, September 1997.
- [Fla97b]
-
David Flanagan.
Java in a Nutshell.
O'Reilly, 2 edition, May 1997.
- [Fla99a]
-
David Flanagan.
Java Foundation Classes in a Nutshell.
O'Reilly, 1 edition, September 1999.
- [Fla99b]
-
David Flanagan.
Java in a Nutshell.
O'Reilly, 3 edition, November 1999.
- [GHJV95]
-
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.
Design Patterns. Elements of Reusable Object-Oriented Software.
Addison-Wesley, 1995.
- [Har97]
-
Eliotte Rusty Harold.
Java Network Programming.
O'Reilly, 1 edition, February 1997.
- [Lea99]
-
Doug Lea.
Concurrent Programming in Java, volume 2.
Addison-Wesley, 1999.
- [LL97]
-
Lohn Lewis and William Loftus.
Java: Software Solutions.
Addison-Wesley, 1997.
- [OW97]
-
Scott Oaks and Henry Wong.
Java Threads.
O'Reilly, 1 edition, January 1997.
- [Tan96]
-
Andrew S. Tanenbaum.
Computer Networks.
International Series. Prentice Hall, third edition, 1996.
- [WFC+99]
-
Seth White, Maydene Fisher, Rick Cattell, Graham Hamilton, and Mark Hapner.
JDBC API Tutorial and Reference: Universal Data Access for the
Java 2 Platform.
Addison-Wesley, second edition, 1999.
- 1
- Java 1.2 hat es auch noch nicht.
Allerdings die Erweiterungen Generic Java und
Pizza.
- 2
- ASCII und ISO-Latin-1 (``mit
Umlauten'') kompatibel
- 3
- aber sich darauf zu verlassen, ist schlechter Stil.
- 4
- Der Operator ?
beipiesweise für bedingte Ausdrucke (<cond>?<expr1> :
<expr2>) ist dreistellig und Mixfix, Inkrement mit
++ ist einstellig und Postfix.
- 5
- Ansonsten
bitweise.
- 6
- Es gibt noch einen zweiten Nutzen von Klassen
wie Integer. Das kommt aber erst später.
- 7
- Alternativ ist auch auch float
height [] = .. erlaubt, ist aber nicht konsistent mit der
Vorstellung, daß die Syntax immer <datatype> <ident> = new
<datatype> lautet.
- 8
- Genauer gesagt: es funktioniert auch mit Objekten,
die eine Methode toString zur Verfügung stellen.
- 9
- break in Schleifen wird manchmal als
schlechter Stil angesehen.
- 10
- Das gleiche gilt für eine Methode ohne
return.
- 11
- Das ist
die offensichtliche Art sich neue Objekte zu schaffen. Eine weitere ist
als Literale in Spezialfällen (Strings, Arrays).
- 12
- Bei
Zweideutigkeiten (lokale Variablen oder Namensgleichheit mit einem
formalen Parameter) innerhalb einer Methode muß man this
verwenden, wenn man die nicht-methodenlokale Variable/Methode meinen
will.
- 13
- Geht auch bei
normalen Methoden, d.h. nicht-Konstruktormethoden.
- 14
- Instanzen
der betrachteten Klasse dürfen den Klassennamen weglassen.
- 15
- static final anstelle von
#define ....
- 16
- Wie man eine
Überbuchung des Kurses verhindert, kommt später.
- 17
- Grund: Math hat viel mit Zahlen zu schaffen,
und das sind feste Werte, keine Objekte.
- 18
- natürlich nicht bei Instantiierung eines
zugehörigen Objektes.
- 19
- Interfaces kommen erst später.
- 20
- d.h. zur Laufzeit
- 21
- Im Endeffekt laufen alle genannten
Dinge auf das selbe hinaus. die Wortwahl kehrt nur verschiedene Aspekte
hervor: Binding bezieht sich auf Compilersichtweise. Dispatch und
message passing eher die das Verhalten der Implementierung zur
Laufzeit.
- 22
- Das
Beispiel während der Vorlesung mit bloß int i;
war falsch, zumindest die erste Ausgabe hatte ich mir
offensichtlich falsch notiert. Es verhält sich wie int i =
0;, was einleuchtet.
- 23
- Warum die Designer von Java Felder
statisch und nicht wie Methoden dynamisch gebunden haben, ist
unbekannt. Beachte: wenn von ``statischer Bindung'' der
Feldvariablen die Rede ist, sind nicht Feldvariablen mit dem
static Modifier gemeint, sondern die normalen
Instanzvariablen. Statisch meint: wenn der Compiler herausfinden muß,
welcher Code bzw. welche Daten zu welchem Namen (hier Methoden- bzw.
Feldnamen) gehören, dann legt er diese Zuordnung oder
Bindung zur Compilezeit fest, sprich: er schaut
in der Klassendefinition nach. Natürlich sind als static
deklarierte Felder und Methoden in diesem Sinne statisch
gebunden. Methodenaufruf dagegen ist in oo-Sprachen
dynamisch.
- 24
- Später, wenn wir Casten
kennengelernt haben werden, kann man den Unterschied auch daran sehen:
Deklarierte man B b; aber verwendete man in der Ausgabezeile
System.out.println("b.x = " + ((A)b).x);, also ``b, gecasted
auf A'', so bekommt man den Wert des Feldes wie er in A deklariert
wird, also 3! Umgekehrt, eine Instanz von A |anders
als etwas was man von ``Typ'' A deklariert hat| kann man nicht nach
B casten, denn es führt zu einem Laufzeitfehler.
- 25
- Am besten, man vermeidet es ganz
indem man Zugriffsmethoden schreibt.
- 26
- Eine Sonderform des
Überschreibens.
- 27
- Kommt später genauer, was das heißt
- 28
- Wäre ergebnis nicht bei der Deklaration bereits
ein Wert zugewiesen worden, hätte der Compiler erkennen können, daß
ich schummele.
- 29
- das Schlüsselwort abstract muß nicht
angegeben werden, ist aber implizit vorhanden.
- 30
- Bei mehreren Interfaces: alle
Methoden. Falls die Interfaces eine Hierarchie bilden, auch noch
deren darüberliegenden Interfaces.
- 31
- Members = bisher Methoden und Felder.
- 32
- Interfaces werden, was Zugriff und Namensresolution
betrifft, genauso behandelt wie Klassen, deswegen werden sie hier nicht
extra genannt.
- 33
- Wenn kein Paket
angegeben, dann an oberster Stufe in einem anonymen default Paket
- 34
- Um damit umzugehen, wird auch die
super-Syntax entsprechend erweitert. Vor dem Gebrauch wird
abgeraten
- 35
- technische Bemerkung: final
deswegen, weil der Compiler Kopien für die lokale Klasse
anfertigt.
- 36
- Man kann ausprobieren, was der
Compiler draus macht: er erzeugt eine neue Klasse
Lister$1.class
- 37
- out ist eine
``Konstante'' (public static final) aus
java.lang.System.
- 38
- PrintStream wird nicht mehr so
gern gesehen in 1.1. Lieber PrintWriter. Allerdings wird man
PrintStream nicht so schnell los...
- 39
- Pufferung wg. Effizienz
- 40
- -1 als
EOF-Rückgabe
- 41
- Zu ersten Anmerkungen zu Applets, siehe auch die einführende
Lektion zu Beginn.
- 42
- die graphische Komponente Frame kommt später genauer, es ist
eine Art top-level Fenster.
- 43
- die Implementierung der Graphiken
ist deviceabhängig, Instanzen von Graphik stellen also ein
deviceunabhängige Schnittstelle zur Verfügung. Graphics2D
ist eine 1.2-Erweiterung von Graphics
- 44
- Bitte
selber in der Klasse nachschauen, was es so gibt.
- 45
- Erweitert gegenüber 1.1
- 46
- Oder über eine ``Map'' = endliche Abbildung,
Assoziationsliste.
- 47
- public static final
- 48
- Siehe auch
http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
- 49
- "`assistive
technology"' ..."`pluggable"', "`trivially configured"',
"`pioneering design"' "`great step forward"',
"`PLAF=pluggable-look-and-feel"'...
- 50
- Mit deutschten Worten wie
"`Komponente"' meine ich hier nur "`graphisches Dings"',
Component sei die konkrete Javaklasse.
- 51
- Erweitert zu LayoutManager2
- 52
- 1.1, 1.2 mit Swing
- 53
- Webbrowser unterstützen oft nur das
Ereignismodell von Java-1.0. (Stand 1999)
- 54
- Wie war das noch mit Java:
``write once, run everywhere, everytime''?
- 55
- in Java 1.0 war es
die Klasse Event.
- 56
- Ausnahme: der Klasse MouseEvent sind1
zwei Listener-Schnittstellen zugeordnet: MouseListener und
MouseMotionListener.
- 57
- Die Adapter hier können
als eine sehr einfache Form der Adapter-Muster
[GHJV95] betrachtet werden.
- 58
- Thread hat
verschiedene Konstruktoren.
- 59
- nicht nur auf die Methode.
- 60
- Streng genommen, keine
deprecated Methode
- 61
- Zwischen Thread.MAX_PRIORITY und
Thread.MIN_PRIORITY. Default:
Thread.NORM_PRIORITY.
- 62
- Je kleiner die Zahl, desto höher die
Dringlichkeit oder Priorität.
- 63
- Fast
immer. Der Fairness halber, um Aushungern einzelner Threads zu
verhindern kann es Ausnahmen geben. In keinem Fall darf die
Korrektheit eines Algorithmusses von Prioritäten oder der
Schedulingstrategie abhängen.
- 64
- oder mit stop abgebrochen wird, was aber
nicht empfohlen wird.
- 65
- z.B. 21 = FTP, 23 = Telnet, etc. Siehe RFC 1700
- 66
- TCP und UDP sind die zwei
Internettransportprotokolle transmission control protocol und
user data protocol.
- 67
- vergleiche das Kapitel über Threads
- 68
- Wie z.B. mittels System.out
- 69
- Zur momentanen IP-Adressierungsschema
s. [Tan96].
- 70
- Man hätte
auch den String im Ganzen übergeben können: URL(protocol
+ "://" + hostname + filename).
- 71
- Das ganze
ist analog dem Vorgehen bei Sockets und Ports oder normalem File-I/O.
Ports gehören zur Transportschicht, während URLs zur
Anwendungsschicht gehören. Ebenfalls zur Anwendungsschicht
gehören die Protokolle ftp, mail, telnet, http, etc.
- 72
- Entspricht ungefähr accept bei
ServerSocket auf Transportschichtebene.
- 73
- Enterprise-Programmierung
ist ein schicker Name für verteilte Anwendungsprogrammierung.
- 74
- das einzige Interface aus
java.rmi.*. Der Rest sind der Klassen dient fast nur der
Ausnahmebehandlung.
- 75
- deswegen sind auch nur die Methoden,
die im Interface genannt sind, von Ferne zugreifbar.
- 76
- überwacht i.d.R. Port 1099
- 77
- man kann auch volle IP-Adressen
verwenden
- 78
- Enterprise, in diesem
Zusammenhang, ist ein fescher Name für "` verteilt"'.
- 79
-
(Structured Query Language), meist SQL-92 bzw. Teilmenge
davon.
- 80
- guter Stil, auch
wenn das Schließen implizit geschehen sollte, z.B., wenn man eine
Verbindung schließt.
- 81
- Es gibt noch übergeordnete
Strukturen (Cluster und Kataloge) oberhalb von Schemata aber die sind
für uns ohne Belang.
- 82
- die letzten 4 können mit
NOT modifiziert werden
July 4, 2000
This document was translated from LATEX by
HEVEA.