Java Skript

Java Skript
Frank Koch, M.B.A., Dipl.-Inf.
[email protected]
 Frank Koch
1
Inhaltsverzeichnis
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
2
2.1
2.2
2.3
2.4
2.5
2.6
2.7
3
3.1
3.2
3.3
3.4
3.5
3.6
4
4.1
4.2
4.3
4.4
4.5
5
5.1
5.2
5.3
5.4
6
7
7.1
7.2
7.3
7.4
7.5
7.6
EINLEITUNG
Administration
Einführung
Entwicklung von Java
Ziele von Java
Java Architektur
Java Security
Java Applications versus Applets
Java Entwicklungsumgebung
Java Syntax
Unterschiede zwischen Java und C++
Struktur von Applets und Applications
Kommentare
Variablen
Operatoren
Kontrollstrukturen
Arrays
Objektorientierung
Einleitung
Klassen und Objekte
Wiederverwendung
Finale Klassen
Abstrakte Klassen
Object Wrappers
Sprachkonzepte
Literale
Parameter
Operatoren
Objektorientierung
Befehlszeilenargumente
Exception Handling
Einführung
Exception Syntax
Checked Exceptions
Unchecked Exceptions
Interfaces
Threads
Einführung
Erzeugen von Threads
Ein Beispiel für Threads
Synchronisation von Threads
Kommunikation zwischen Threads
Interfaces
 Frank Koch
8
8.1
8.2
9
9.1
9.2
9.3
9.4
9.5
9.6
10
10.1
10.2
10.3
10.4
10.5
11
11.1
11.2
11.3
12
12.1
12.2
12.3
13
13.1
13.2
13.3
14
15
15.1
15.2
15.3
16
16.1
16.2
16.3
17
Java API: Die Standard Java Packages
Packages
Java Core Packages
User Interface
Einführung
Container und Layouts
Menüs
Kontrollelemente
The Java Event Model
Interne Klassen / Nested Classes
Applet-Programmierung
Einführung
Kontrollmethoden
Events
Übung
Applets und Threads
Input/Output
Klassenübersicht
System.in und System.out
File I/O
Kommunikation über das Internet
Zugriff auf eine URL
Client/Server Programmierung mit
Sockets
POP3-MailClient
JDBC
JDBC – Datenbankzugriff in Java
JDBC – Anwendungsbeispiel
JDBC – Übung
CGI
Servlets
Sinn und Zweck
Installation
Servlet-Demonstrationen
JavaScript
Positionierung
Beispiel
Bedeutung für Java
Javadoc
2
Java Literaturempfehlung
Java in 21 Tagen
• Laura Lemay, Rogers Cadenhead
• Markt & Technik Buch und Softwareverlag
• ISBN 382726281X
• erschienen am 15. November 2001
• 864 Seiten plus CD mit J2SE und HTMLBuchtext
• EUR 44,95
Weitere Empfehlungen:
• The Java Tutorial: Object-Oriented Programming for the Internet, Mary Campione and Kathy Walrath (Dieses Buch
brauchen Sie nicht kaufen. Es steht Ihnen komplett auf dem
Internet (java.sun.com) zur Verfügung.
• The Java Programming Language, Ken Arnold, James
Gosling, Addison Wesley, ISBN-0-201-63455-4
• Java in a Nutshell, David Flanagan, 39 DEM, O'Reilly & Associates, Inc., ISBN 3-930673-46-0
• Java bis ins Detail, G.Cornell, C.S. Horstmann, HeiseVerlag, ISBN 3-88229-087-0
• Instant Java,I.A. Pew, Heise-Verlag, ISBN 3-88229-084-6
• Java pur, P.v.d. Linden, Heise-Verlag, ISBN 3-88229-086-7
• Java Primer Plus, Paul Tymon, 39.99 USD, Wait Group
Press, ISBN 1-57169-062-x
• Programmieren in Java, Brian Stark, Franzis Verlag, ISBN 37723-4432-1
 Frank Koch
3
Java Online Quellen
JAVA Standardwerke
•
http://java.sun.com/nav/read/whitepapers.html
Die White Papers. Die Entwicklungs- und Hintergrunddokumentationen der Javaentwickler
•
http://java.sun.com/doc/api_documentation.html
Die Java Klassenbibliothek von SUN Microsystems. Ein Listing aller im JDK zur Verfügung stehenden Klassen
•
http://java.sun.com/nav/read/tutorial.html
Das Java Tutorial von SUN. Eine sehr ausführliche Dokumentation für alle Lebenslagen. Datei
kann als ZIP-file (Größe ca.1,7 MB) geladen werden. Zum Entkomprimieren benötigen Sie einen Entpacker, der lange Dateinamen berücksichtigt (z.B. WinZip).
•
http://java.sun.com/doc/language_specification.html
The Java Language Specification. Eine Dokumentation der Programmiersprache Java Java.
•
http://java.sun.com/doc/language_vm_specification.html
The Java Virtual Machine Specification. Beschreibung der Java VM und deren Befehlssatzes
•
http://java.sun.com/products/JDK/debugging/index.html
The The Java Language Debugging. Anleitung zur Verwendung des Java Debuggers (JDB)
Interessante Java Seiten
•
http://www.java.de/
Java User Group Deutschland. Artikel und Links, sowie Aktuelles zum Thema
•
http://acc.de/java
Kaffee & Kuchen. Artikel und Links, sowie Aktuelles zum Thema
•
http://www.javaworld.com/
Javaworld. Eine monatliche Zeitschrift, die nur im Internet erscheint. Artikel rund um Java und
andere Internettechnolgien. Sehr gut!
•
http://www.jars.com/
Die Jars Page. Hier werden die besten Javapages gekürt. Hier findet man die besten und kuriosesten Javaapplets, manchmal auch mit Sourcecode!!
Newsgroups
•
news://de.comp.lang.java
Die Deutsche Java Newsgroup. Hier kann man Neuigkeiten erfahren, Fragen stellen und Tips
erhalten.
•
news://comp.lang.java.announce
•
news://comp.lang.java.advocacy
•
news://comp.lang.java.programmer
•
news://comp.lang.java.tech
•
news://comp.lang.java.setup
 Frank Koch
4
Java Entwicklungsgeschichte
• 1991: Beginn der Java Entwicklung (im gleichen Jahr, als das WWW
entstand) in Hause SUN. Der Java-Entwickler (James Gosling) dachte
zunächst nicht an das Internet. Sein Ziel war es eine gemeinsame
Entwicklungsplattform für elektronische Konsumgüter (set-top boxes
für interaktives TV, PDA, etc) zu erstellen. Dazu benötigte sein Team
eine Pgmiersprache, mit der diese Produkte gesteuert werden konnten und die leicht von einem Gerät auf ein anderes portiert werden
konnte. Zunächst benutzte das Java Entwicklungsteam C++ als Sprache. Sie realisierten schnell, dass sie eine robustere Sprache mit
mehr Unterstützung für Sicherheit und Portabilität benötigten. Diese
Bemühungen führten zur Entwicklung der Sprache Oak (die 1995 aus
produktrechtlichen Gründen in Java umbenannt wurde). Diese Sprache ist stark an die C++-Syntax angelehnt, dabei aber einfacher und
plattformunabhängiger.
• 1992: Das Oak-Team war soweit den Projektstatus SUN zu präsentieren, was zur Gründung eines eigenen Unternehmens mit dem Namen
FirstPerson führte. Der Plan war es Oak den wichtigsten Herstellern
von Consumerelektronikgeräten nahezubringen. Doch der Markt war
noch nicht reif für das, was FirstPerson anzubieten hatte.
• 1994: kam das Aus für FirstPerson; niemand wollte Oak lizensieren.
Zu dieser Zeit war die Welt bereits vom Internet-Fieber erfasst und
SUN verstärkte seine Bemühungen auf diesem Gebiet. Das OakTeam realisierte ein fundamentales Problem mit Web-Pages: sie sind
„flat“, d.h. sie erlauben dem Surfer keine Interaktion mit den Daten,
die auf einer Seite dargestellt werden. „Das Web braucht Interaktivität“, ist die Idee, die dem Oak-Team neuen Anstoss gab.
• 1994: Sun released WebRunner und HotJava, zwei in Java entwickelte Browser. Diese neue Technologie fand das Interesse von Netscape, die ankündigten, mit ihrem populären Browser Netscape Navigator künftig Java zu unterstützen.
• 1995: Oak wird aus urheberrechtlichen Gründen in Java umgetauft.
• 1996: Der verbreitete Netscape Navigator unterstützt Java
• 1997: JDK 1.1; viele neue Klassen unterstützen den Entwicklungsprozess1998: JDK 1.2
• Java IDL und RMI (wird für Client/Sever Entwicklungen benötigt)
• Swing (GUI Library)
• 2001: Present version: 1.3.1 (subset of J2SE)
• 2002: J2SE (with SDK) 1.4
 Frank Koch
5
Java Entwicklungsziele
Hauptziele
• Portabilität / Plattformunabhängigkeit
Das gleiche Programm läuft auf allen
Plattformen, die einen JavaInterpreter besitzen. Für Anwendungen im Internet ein Muss!
• Verteilte Anwendungen
Neben normalen Applikationen erlaubt Java die Erstellung von Applets, welche durch einen Web-Browser
geladen werden können. Diese Applets werden in die
HTML-Seiten integriert und über das Internet von den
Hostrechnern geladen. Damit ist die Realisierung von
verteilten Anwendungen möglich.
• Robustheit / Sicherheit
Durch mehrstufiges Sicherheitskonzept.
Nebenziele
• Objektorientierung
Im Gegensatz zu C++ kann in Java nicht mehr konventionell programmiert werden.
• Evolution
Anlehnung an den Industriestandard C und C++ bei
gleichzeitiger Verbesserung der C/C++-Schwächen.
• Hohe Performance
Durch parallele Prozesse (Threads). Trotzdem: als interpretierte Sprache ist Java etwa um den Faktor 20
langsamer als C++.
• Java stellt Mechanismen zur Einbindung von InternetRessourcen (z.B. URL) zur Verfügung.
 Frank Koch
6
Java Architektur
Java Architecture
Traditional
3GL Architecture
Source Code
Hello.java
Source Code
Hello.c
Java
Compiler
Compiler
Object Code
Byte Code
Hello.class
Linker
Machine Code
JVM
 Frank Koch
OS
OS
CPU
CPU
7
Java Security
Developer Platform
Source Code
Hello.java
Security Level 1
Language and Compiler
Internet
Client-Platform
Bytecode
Hello.class
JVM
Security Level 2
Bytecode Verifier
Security Level 3
Class Loader
Security Level 4
Sandbox Model
 Frank Koch
8
Java Sandbox Model
• Für Applets ist kein lokaler Dateizugriff erlaubt
(delete, read, write to local files)
• Applets dürfen keine Betriebssystembefehle aufrufen (z.B. können keine Verzeichnisse erstellt
werden bzw der Inhalt von Verzeichnissen gelesen werden)
• Applets dürfen keine lokalen Programme ausführen oder DLLs aufrufen
• Applets dürfen keine Netzwerkverbindungen öffnen, ausser zu dem Host, von dem sie geladen
wurden. Damit ist es dem Benutzer möglich, Dateien zu speichern. Zwar nicht auf seiner Disk
aber auf der des Applet-Hosts. Auf diese Weise
kann mittels Applets eine wahre Client/Server
Architektur gebaut werden.
 Frank Koch
9
Application versus Applet
Unterschiede:
• Eine Application verhält sich wie ein Stand Alone-Programm.
• Applets können nur innerhalb eines Java-kompatiblen Containers
(z.B. ein Browser) ausgeführt werden. Applikationen hingegen können
mittels einer kleinen Boot Utility (JAVA.EXE) von der Command Line
ausgeführt werden.
Applets werden unter strikten Sicherheitsbeschränkungen (SandboxModel) ausgeführt. Applikationen haben keine solchen Sicherheitsbeschränkungen.
• Applets können in eine HTML Page eingebunden (embedded) werden, über das Internet oder ein Intranet verteilt werden und innerhalb
eines Browsers ausgeführt werden. Applikationen haben keine Unterstützung für HTML-Embedding oder Downloading.
Gemeinsamkeiten:
• Beide Programme werden aus einem oder mehreren Dateien mit der
.CLASS extension erstellt und enthalten maschinenunabhängigen Java-Bytecode.
• Beide Programme erfordern eine installierte Java Virtual Machine
(JVM). Die JVM lädt das Programm, interpretiert es und stellt dem
Programm die Java core packages (the standard library) zur Verfügung.
•
Application
public class FirstApplication
{
public static void main(String Args[]) {
// Java source code goes here.
}
}
Applet
import java.applet.*;
public class FirstApplet extends Applet {
//Java source code goes here.
}
 Frank Koch
10
HTML APPLET-Tag
<APPLET
CODE=MyApplet.class
CODEBASE=“http://www.zhwin.ch/swk“
ID=FirstApplication
WIDTH=320
HEIGHT=240 >
</APPLET>
CODE
CODEBASE
ID
WIDTH
HEIGHT
Spezifiziert die zu ladende Java Bytecode Datei.
Optional: Eine gültige URL, die auf das Verzeichnis verweist, in dem sich die .CLASS-Datei des Applets befindet.
Dieses Tag wird notwendig, wenn sich die .CLASS-Datei
in einem anderen Verzeichnis befindet als die HTMLDatei.
Unter diesem Namen kann das Applet in dem HTMLDokument referenziert werden.
Optional: Spezifiziert die Breite des Applet Windows.
Optional: Spezifiziert die Höhe des Applet Windows.
PARAM-Tag
Hiermit können dem Applet Parameter aus der HTML-Datei übergeben werden
<APPLET
CODE=MyApplet.class
ID=FirstApplication
WIDTH=320
HEIGHT=240 >
<PARAM name=Message value=“Hello“>
</APPLET>
Alternate HTML
Alternativer Text für nicht-javafähige Browser
<APPLET
CODE=outline.class
HEIGHT=150
WIDTH=200>
You're missing a Java outline applet.
<UL>
<LI><A HREF="default.htm">Internal Training Home Page</A></LI>
<LI><A HREF="States.htm">Location Courses are Offered</A></LI>
</UL>
</APPLET>
 Frank Koch
11
Erstellen einer Java Application
Erstellen eines Java Source Files
Erstellen Sie mit einem Editor die Datei Hello.java mit dem folgenden
Java code:
/**
* The Hello class implements an application that
* simply displays "Hello World!" to the standard output.
*/
class Hello {
public static void main(String[] args) {
System.out.println("Hello World!"); //Display the string.
}
}
Compilation des Sources
Compilieren Sie die Source mit dem Java Compiler.
javac Hello.java
Bei fehlerfreier Compilation erstellt der Compiler die Datei Hello.class
(gleiches Verzeichnis wie Hello.java). Diese Datei enthält den plattformunabhängigen Java Bytecode, der von einem Java runtime system interpretiert werden kann.
Starten der Applikation
Starten Sie das Programm mittels des Java Interpreters.
java Hello
Die Ausgabe "Hello World!" sollte erscheinen.
 Frank Koch
12
Erstellen eines Java Applets
Erstellen eines Java Source Files
Erstellen Sie mit einem Editor die Datei HelloApp.java mit dem folgenden Java
code:
import java.applet.Applet;
import java.awt.Graphics;
public class HelloApp extends Applet {
public void paint(Graphics g) {
g.drawString("Hello world!", 50, 25);
}
}
Compilation des Sources
Compilieren Sie die Source mit dem Java Compiler.
javac HelloApp.java
Bei fehlerfreier Compilation erstellt der Compiler die Datei HelloApp.class
(gleiches Verzeichnis wie HelloApp.java). Diese Datei enthält den plattformunabhängigen Java Bytecode.
Erstellen einer HTML-Datei, die das Applet einbindet
Erstellen Sie mit einem Editor die Datei Hello.html mit dem folgenden HTML
code:
<HTML>
<HEAD>
<TITLE> A Simple Program </TITLE>
</HEAD>
<BODY>
Here is the output of my program:
<APPLET CODE="HelloApp.class" WIDTH=150 HEIGHT=25>
</APPLET>
</BODY>
</HTML>
Starten des Applets
Um das Applet zu starten müssen Sie die HTML-Datei in eine Applikation laden, die Java Applets ausführen kann. Dazu können Sie einen Javakompatiblen Browser oder ein anderes Java Applet Darstellungsprogramm
(z.B. AppletViewer aus dem JDK) benutzen. Um die HTML-Datei zu laden geben Sie der Applikation die URL der HTML-Datei an, z.B.:
file:/d:/Java/Src/Hello/HelloApp.html
Um das Applet mit dem AppletViewer anzusehen, wechseln Sie in das AppletVerzeichnis und geben ein:
appletviewer HelloApp.html
 Frank Koch
13
Übung Application versus Applet
Erstellen (Codierung, Compilierung, Ausführung) Sie die
Java-Application Hello.java sowie das Java-Applet HelloApp.java gemäss der Beschreibungen "Erstellen einer
Java Application" sowie "Erstellen eines Java Applets"
weiter oben im Skript.
Legen Sie die Codeteile im Verzeichnis java\Src\Fundamentals\Hello an.
 Frank Koch
14
Unterschiede zwischen Java und C++
• Java stellt Unterstützung für Kommunikation
und verteilte Verarbeitung zur Verfügung
• Java Compiler erstellen maschinenunabhängigen Bytecode, der eine Java Virtual Machine
erfordert. C++ Compiler hingegen erstellen
Maschinencode.
• Java kann stand-alone-Applikationen erstellen
oder aber Applets, die über das Internet zugänglich auf HTML Web Pages aktiviert werden. Mit C++ hingegen kann man nur standalone Applikationen erstellen.
• Java Applikationen linken alle notwendigen
Klassen dynamisch zur Laufzeit. C++ Applikationen hingegen linken die Klassen statisch zur
Compilierzeit.
• Java unterstützt nur „named references“ auf
Speicheradressen. C++ hingegen unterstützt
named references sowie pointers und damit
Pointerarithmetik. Klartext: Java kennt keine
Pointer.
• Java hat automatische Garbage Collection. In
C++ hingegen muss diese vom Pgmierer besorgt werden.
 Frank Koch
15
Definition von Variablen
/* Single variables */
byte myAge;
String myTitle;
// Multiple variable declared on a single line
int myAge, yourAge, herAge;
/* Constant */
final boolean isSmart = true;
Variablen sollten initialisiert werden, denn nicht-initialisierte Variablen
können nicht gelesen werden.
//0 is used to initialize numeric variables
int x=0;
//null is used to initialize objects
String person = null;
//null character is used to initialize characters
char x='\0';
//false is used to initialize Booleans
boolean isMarried = false;
Datentypen von Variablen
Der Datentyp einer Variablen kann einer der acht primitiven
Datentypen, eine build-in oder user-defined Klasse oder ein
Array sein.
float x;
Float x;
Student x;
int[] x;
 Frank Koch
//float is a primitive data type
//Float is a built-in object
//Student is a user-defined class
//int[] is an array of Integers
16
Primitive Datentypen
Java bietet acht primitive Datentypen zur Behandlung von
Ganzzahlwerten, Fliesskommawerten, Zeichen und Boolschen
Werten. Diese Datentypen sind Bestandteil der Sprache Java
und keine Objekte. Allerdings bietet Java Object Wrappers für
diese Typen, so dass primitive Datentypen wie Objekte benutzt werden können.
Reserved
Word
byte
Data Type
Size
Range of Values
1 byte
-128 to 127
short
int
Byte-length integer
Short integer
Integer
2 bytes
4 bytes
long
Long integers
8 bytes
float
Single precision numbers
Real numbers
with double
precision
Character (16bit Unicode)
Has value
4 bytes
-32,768 to 32,767
-2,147,483,648 to
2,147,483,647
-9,223,372,036,854,775,808 to
9,223,372,036,854,775,807
1.40239846e-45 to
3.40282347e+38
4.94065645841246544e-324 to
1.7976931348623157e+308
double
char
boolean
8 bytes
2 bytes
N/A
true
oder
false
Ein Boolscher Wert true oder
false (nicht wie in C++: 1 oder 0)
Beachten Sie, dass char als Unicode benutzt wird. Unicode ist
ein 16-bit character set, welches eine Standardzuordnung aller
weltweit bekannten Zeichen definiert. WindowsNT benutzt
ausschliesslich Unicode auf der Systemebene.
 Frank Koch
17
Operatoren für primitive Datentypen
Arithmetische Operatoren
+, -, *, /, %
Zuweisungsoperatoren
=, +=, -=, *=, /=, %=
Inkrement- und Dekrement (Post- und Präfix)
++, -Relationale Operatoren (liefern boolean)
==, !=, <, <=, >, >=
 Frank Koch
18
Arten von Kontrollstrukturen
Niklaus Wirth: „Programme bestehen aus Daten und Algorithmen“
Drei unterschiedliche Befehlsabläufe sind möglich:
Sequentielle Abläufe
Vergleichende Abläufe / Selektion
?
Ja
Nein
Wiederholende Abläufe / Iteration
?
Ja
Nein
 Frank Koch
19
Kontrollstrukturen
Selektion:
if (<bedingung>) {
<true-statement>
}
else {
<false-statement>
}
switch (<ausdruck>) {
case 1: <statement>
case 2: <statement>
...
case N: <statement>
default: <statement>
}
Iteration:
while (<bedingung>) {
<statements>
}
do {
<statements>
} while (<bedingung>)
for (<initialisierung>;<bedingung>;<inkrement/dekrement>) {
<statements>
}
 Frank Koch
20
Kontrollstrukturen
• Klammert man die Befehle innerhalb einer Kontrollstruktur nicht zu einem Block, so wird nur der erste
auf die Kontrollstruktur folgende Befehl abhängig von
der Kontrollstruktur ausgeführt.
• Kontrollstrukturen können ineinander geschachtelt
werden.
Was passiert im folgenden Beispiel?
int b = 0;
int a = ?;
// ? muss ersetzt werden
if (a > 1)
if (a > 2)
b = 1;
else
b = 2;
a sei
Dann wird b zu
1
2
3
Oder aber…
 Frank Koch
21
Logische Operatoren
Logische Operatoren
&&, ||, !, ^^ (XOR)
Mit den logischen Operatoren lassen sich Bedingungen verknüpfen, z.B.:
if ((alter > 16) && (alter < 40))
System.out.println(“Voller Preis“);
Die Entscheidungstabellentechnik hilft beim Aufbau der Bedingungen.
• Es sitzen drei Zauberer im Theater, der eine in der ersten Reihe, der
Zweite gleich hinter ihm, in der zweiten Reihe und der Dritte in der
dritten Reihe, hinter dem Zweiten. Der erste Zauberer sieht also keinen, der Zweite sieht den Ersten und der Dritte sieht beide.
• Es gibt 5 Kappen im Theater, 3 schwarze und 2 weisse. Die Zauberer
wissen das. Man hat allen drei je eine schwarze Kappe aufgesetzt,
ohne dass die Zauberer selbst das gesehen haben.
• Wer von den Zauberern ruft als erster aus, dass seine Kappe schwarz
ist?
• Natürlich dürfen die Zauberer nicht nach hinten schauen oder miteinander reden.
 Frank Koch
22
Weitere Operatoren
Bitwise Operators
Bitwise operators manipulate the individual binary digits (bits) of a value as it is actually stored in computer memory. For example, the decimal number 32 would be
represented as 0010000 in base 2-bit values. Using the bitwise operators shown in
the table below, you can work with these values directly.
Operator
&
|
^
~
Description
AND bitwise operator
OR bitwise operator
XOR bitwise operator
Bitwise complement
Example
x = y & 64
x = y | 24
x=y^z
x=~y
Logical Assignment Operators
The logical assignment operators are really shorthand for the regular assignment
operator (=) and the Boolean bitwise operator..
Operator
&=
|=
^=
<<=
>>=
>>>=
Description
AND assignment
OR assignment
XOR assignment
Left shift assignment
Right shift assignment
Unsigned right shift assignment
Example
x&=y
x|=y
x^=z
x=<<y
x=>>z
x>>>=y
Shift Operators
The left and right shift operators move all of the bits in an integral value to the left
or right. In an expression of the form of x<<y, x is the number being shifted and y is
the distance to shift x. For example, 10<<1 is equal to 20. In other words, leftshifting a number by y is equivalent to multiplying the number by 2y. Conversely,
right-shifting a number is equivalent to dividing a number by 2y. The computer's
processor is actually faster at performing shift operations than at multiplying or dividing a number by 2y.
Operator
<<
>>
>>>
 Frank Koch
Description
Left shift
Right shift
Unsigned right shift
Example
x<<y
x>>z
x>>>y
23
Operatoren Rangfolge
The following table contains a listing of Java operators in descending
order of precedence. The operators with the highest precedence are at
the top.
Operator
[]
()
.
Operator Type
array index
parameter list
method invocation
++,-arithmetic
+, arithmetic
~
integral
!
Boolean
(type)
any
*, /, %
arithmetic
+, arithmetic
+
string
<<
integra
>>
integra
>>>
integra
<, <=
arithmetic
>, >=
arithmetic
instanceof object, type
==
primitive
!=
primitive
==
object
!=
object
&
integral, Boolean
^
integral, Boolean
|
integral, Boolean
&&
Boolean
||
Boolean
?:
Boolean, any, any
=
variable, any
*=, /=, %=, +=, -=, variable,
<<=, >>=, >>>=,
any
&=, ^=, |=
 Frank Koch
Description
Used to access elements of an array
Denotes a list of parameters
Used to specify a method within an
object (or its hierarchy)
Pre- or post-increment/decrement
Unary plus, unary minus
Bitwise complement (unary)
Logical complement (unary)
Cast
Multiplication, division, remainder
Addition, subtraction
String concatenation
Left shift
Right shift with sign extension
Right shift with zero extension
Less than, less than or equal
Greater than, greater than or equal
Type comparison
Equal (have identical values)
Not equal (have different values)
Equal (refer to the same object)
Equal (refer to different objects)
Bitwise AND, Boolean AND
Bitwise XOR, Boolean OR
Bitwise OR, Boolean OR
Conditional AND
Conditional OR
Conditional (ternary)
Assignment
Assignment with operation
24
Literals 1
Literals are used to indicate explicit values in your programs. Java has
four kinds of literals: numbers, characters, strings, and booleans.
Numeric Literals
There are two types of numeric literals: integers (numbers without
decimals) and floating-point numbers (numbers with decimals).
Integer literals can be in decimal, octal, or hexadecimal format. Decimal
integers are the most common format, and Java assumes all numbers
to be decimal unless otherwise noted. Octal integers, which are far less
common, are distinguished by a zero in front of the number: 0123.
Hexadecimal numbers have a 0x or 0X in front of them: 0xFFFF. Java
stores integer literals as 4-byte integers by default. However, if you
place the letter l or L after the number, Java will store it as an 8-byte
integer.
Floating-point literals represent numbers with decimals. In addition to
standard notation, you can use scientific notation to represent very
large or very small numbers:
5.67 or 2.0467e-22 or 3.5999e94 or -4.2370e96
Normally, a floating point literal is 4 bytes long. For double-precision
values with an 8-byte length, you can add the letter d or D after the
number.
Character Literals
A character literal is a Unicode character enclosed in single quotation
marks. Any character in the 16-bit character set may be used. A backslash is used to denote non-printing characters, such as carriage returns and tabs. Some of the more commonly used escape sequences
are shown in the following table.
Description
Line feed
Carriage return
Horizontal tab
Backspace
Backslash
Single quote
Double quote
 Frank Koch
Escape Sequence
\n
\r
\t
\b
\\
\'
\"
25
Literals 2
String Literals
String literals are characters enclosed in double quotation marks. They
can have the same escape sequences as single character literals. Java
uses a String class to implement strings, whereas C and C++ use an
array of characters. Example: “Hello World“
Boolean Literals
Boolean literals can have two possible values: true or false. In Java,
true and false do not correspond to the numeric values 1 and 0, as do
Booleans in C and C++. Boolean literals are often used as flags for
program flow control. For example, the following code sample will
change the status bar if the isScrolling() method returns true.
boolean x=false;
Marquee m = new Marquee("Scrolling message");
x = m.isScrolling();
//If x is true then change the status bar to this message
if (x)
showStatus("Text is scrolling");
 Frank Koch
26
Parameter und Local Variables
Im folgenden Pgm ist g eine Parameter-Variable und i eine lokale Variable. Eine Parameter-Variable hat den Scope der Methode, während eine lokale Variable den Scope des Blockes
hat, in dem sie definiert wurde.
import java.awt.*;
public class twos extends java.applet.Applet
{
public void paint(Graphics g)
{//g is local to the paint method
for (int i=0;i<100;i+=2)
{
//i is local to the for statement
g.drawString("Number: "+i,10,5*i);
}
// i dies here
}
}
 Frank Koch
27
Arrays
Arrays sind Referenzvariablen, die einen für die Aufnahme der Variablen bereitgestellten Speicherbereich referenzieren.
Beispiel für die Definition einer Array-Referenzvariablen:
int[] intArray;
In der eckigen Klammer darf keine Zahlenangabe für die Anzahl Elemente eingegeben werden.
Mit dieser Anweisung wird lediglich die Referenzvariable definiert; ein
Speicherbereich für die Arrayelemente steht damit noch nicht zur Verfügung. Das eigentliche Array muss erst noch dynamisch geschaffen
werden und die Array-Referenzvariable mit dessen Adresse initialisiert
werden.
int[] intArray;
intArray = new int[4];
Damit werden vier Speicherplätze vom Typ int angelegt, auf welche
nun die Array-Referenzvariable zeigt. Die Speicherplätze sind von 0 bis
n-1 indexiert:
intArray[0]; intArray[1]; intArray[2]; intArray[3];
Die Feldgrösse kann über die öffentliche Variable length gelesen (nicht
geschrieben!) werden:
intArray.length;
Im Gegensatz zu C prüft Java zur Laufzeit, ob die Arraygrenzen eingehalten werden!
 Frank Koch
28
Strings
Strings sind Objekte. Beispiel für die Definition eines String-Objektes:
String str;
str ist nun zwar definiert, enthält aber noch keine gültige Objektreferenz. Erst durch eine Zuweisung wird der Bezug zur Zeichenkette hergestellt:
str = "Irgendwas";
Das folgende Programm zeigt die Verwendung der auf Stringobjekte
anwendbaren Methoden:
class TestString
{
public static void main(String[] args)
{
String str;
str = "Java";
System.out.println(str.length());
str = str + " ist objektorientiert";
System.out.println(str.length());
System.out.println(str.charAt(11));
System.out.println(str.indexOf("orient"));
System.out.println(str.substring(20, 24));
System.out.println(str);
}
}
Ausgabe:
4
25
j
15
tier
Java ist objektorientiert
 Frank Koch
29
Übung Sort
Erstellen Sie ein Java-Programm, in dem Sie ein Array
mit 10 Elementen mit Werten initialisieren.
Sortieren Sie die Zahlenfolge anschliessend in aufsteigender Reihenfolge.
Geben Sie die Werte vor und nach dem Sortieren aus.
Benutzereingaben sind nicht erforderlich!
Die Lösung finden Sie im Anhang.
Übung Zeichenkette
Konvertieren Sie die Zeichen in einem String in
GROSSBUCHSTABEN und kehren Sie die Reihenfolge der in dem String befindlichen Buchstaben.
Die Klasse String stellt Ihnen hierzu hilfreiche Methoden zur Verfügung. Suchen Sie in der Online-Hilfe
nach der Dokumentation zu dieser Klasse.
Die Lösung finden Sie im Anhang.
 Frank Koch
30
Anhang: Lösung Sort
public class Sort
{
public static void main ( String[] args )
{
final int size = 10;
int i, j, tmp;
int[] array = new int[size];
// Init Array
for (i=0; i<size; i++)
array[i]=size-i;
// Ausgabe
for (i=0; i<size; i++)
System.out.println(array[i]);
// Bubble-Sort
for (i=0; i<size-1; i++)
{
for (j=i+1; j<size; j++)
{
if (array[i] > array[j])
{
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
}
// Ausgabe
for (i=0; i<size; i++)
System.out.println(array[i]);
}
}
 Frank Koch
31
Anhang: Lösung Zeichenkette
public class Zeichenkette
{
public static void main ( String[] args )
{
String str = "Zeichenkette";
String tmp = "";
// In Grossbuchstaben konvertierte Ausgabe
System.out.println(str.toUpperCase());
// Reversierte Ausgabe (algorithmische Lösung)
for(int i=str.length()-1; i>=0; i--)
tmp = tmp + str.charAt(i);
System.out.println(tmp);
// Reversierte Ausgabe (objektorientierte Lösung)
StringBuffer sb = new StringBuffer(str);
sb.reverse();
System.out.println(sb);
}
}
 Frank Koch
32
OO (Klassen und Objekte)
Klasse Point
•
•
•
•
•
x-Koordinatenwert
y-Koordinatenwert
Setzen der
Koordinatenwerte
Lesen der
Koordinatenwerte
Ausgabe der
Koordinatenwerte
Objekt a (1, 3)
Objekt c (3, 3)
Objekt b (1, 1)
Datei Point.java
class Point
{
// Datenteil
private static int s_no; // Klassenvariable = 0
private int m_x, m_y; // Information Hiding!
}
// Methodenteil
public Point(int x, int y) { // Konstruktor!
s_no++;
setX(x);
setY(y);
}
public void setX(int x) {if(x>0) m_x=x; else x=0;}
public void setY(int y) {if(y>0) m_y=y; else y=0;}
public int getX() {return m_x;}
public int getY() {return m_y;}
public void print() {
System.out.print("Punkt: ");
System.out.print("x:" + m_x);
System.out.println(" y:" + m_y);
}
public static void printNo() { // Klassenmethode
System.out.println("Anzahl: " + s_no);
}
public static void main (String[] args ) {
Point a=new Point(1,3);
Point b=new Point(1,1);
Point c=new Point(3,3);
c.setX(10); c.setY(-5);
System.out.println(c.getX() + " " + c.getY());
a.print(); b.print(); c.print();
System.out.println("Wir fragen ein Objekt");
a.printNo();
System.out.println("Wir fragen die Klasse");
Point.printNo();
}
Klasse: Kopplung von Daten und Funktionen zu einem Typ. Ist eine Deklaration / Schablone.
Objekt / Instanz / Exemplar: Instanz der Klasse. Ist eine Definition / Speicherreservation.
Instanzvariable / Membervariable / Objektvariable: In der Klasse definierte Daten.
Methode: In der Klasse definierte Funktionen.
 Frank Koch
33
OO (Wiederverwendung 1)
Arten der Beziehungen zwischen Klassen:
Beziehung
Beispiel
Syntaktische Lösung
"Besteht aus"Beziehung
(Stückliste)
"Ist ein"Beziehung
Ein Dreieck (Triangle)
besteht aus drei Punkten (Point).
Ein gefülltes Dreieck
(FilledTriangle) ist ein
Dreieck mit zusätzlichen Eigenschaften
(Farbe).
Objekte als Instanzvariablen
Vererbung
Notation:
"B esteht aus"
P oint
"Ist ein"
P oint
Triangle
Triangle
P oint
P oint
FilledTriangle
Vererbung:
FilledTriangle
Triangle
getA
print
setA
a, b, c
getB
setC
setB
getC
color
setColor
print
 Frank Koch
getColor
34
OO (Wiederverwendung 2)
Datei Triangle.java
class Triangle
{
// Datenteil
private Point m_a, m_b, m_c;
}
// Methodenteil
public Triangle() {
m_a = new Point(0,0);
m_b = new Point(0,0);
m_c = new Point(0,0);
}
// Overloading Constructor
public Triangle(Point a, Point b, Point c) {
m_a = a; m_b = b; m_c = c;
}
public void setA(Point a) {m_a = a;}
public void setB(Point b) {m_b = b;}
public void setC(Point c) {m_c = c;}
public Point getA() {return m_a;}
public Point getB() {return m_b;}
public Point getC() {return m_c;}
public void print() {
System.out.println("Triangle: ");
m_a.print(); m_b.print(); m_c.print();
}
public static void main (String[] args ) {
Point p1 = new Point(1,1);
Point p2 = new Point(2,2);
Point p3 = new Point(3,3);
Triangle t1 = new Triangle(p1, p2, p3);
Triangle t2 = new Triangle();
t1.print(); t2.print();
}
Regeln für mehrere Klassen in einer .JAVA-Source:
• Genau eine Klasse kann public deklariert sein. In diesem Fall muss die .java-Datei den Namen
dieser Klasse tragen.
• Jede Klasse kann eine eigene main()-Methode besitzen
• Der Compiler generiert zu jeder Klasse ein .class-File
 Frank Koch
35
OO (Wiederverwendung 3)
Datei FilledTriangle.java
class FilledTriangle extends Triangle
{
// Datenteil
String m_color;
}
// Methodenteil
public FilledTriangle() {
super();
m_color = "white";
}
// Overloading Constructor
public FilledTriangle(
Point a,Point b,Point c,String col){
super(a, b, c);
m_color = col;
}
public void setColor(String c) {m_color = c;}
public String getColor() {return m_color;}
// Overriding method print()
public void print() {
System.out.println("FilledTriangle: ");
super.print();
System.out.println(m_color);
}
public static void main (String[] args ) {
Point p1 = new Point(1,1);
Point p2 = new Point(2,2);
Point p3 = new Point(3,3);
FilledTriangle ft1 =
new FilledTriangle(p1, p2, p3, "red");
FilledTriangle ft2 = new FilledTriangle();
ft1.print(); ft2.print();
}
 Frank Koch
36
Übung Objektorientierung
Aufgabe 1
Sie erhalten die Source zu den Klassen Line und GraficLine.
Untersuchen Sie diesen Code und wiederholen Sie daran die
vorgestellten objektorientierten Konzepte (Polymorphismus,
Encapsulation, Inheritance, Constructor, ...).
Aufgabe 2
Erweitern Sie den Code gemäss folgender Aufgabenstellungen:
• Setzen Sie die Farbe eines FilledTriangle-Objekts auf „blue“.
• Es soll sichergestellt werden, dass ein Punkt nur innerhalb
eines Koordinatensystems mit der Ausdehnung x=100 und
y=100 erstellt werden kann. Wird ein grösserer Wert von
dem Benutzer der Klasse spezifiziert, so muss dieser auf den
maximal möglichen Wert 100 gekürzt werden.
• Inkrementieren Sie den x-Wert eines Punktes eines konkreten FilledTriangle-Objekts um den Wert 1 (sofern der Wert
100 nicht überschritten wird).
• Ermöglichen Sie, dass ein FilledTriangle-Objekt Auskunft über die Anzahl instanziierter Objekte seiner Klasse Auskunft
geben kann.
 Frank Koch
37
Method Overloading
Method overloading allows you to supply the same name for two or
more methods within the same class. Each method signature in an
overloaded set must differ in the number and/or types of its parameters.
General methods and constructors can be overloaded. Following an
example that demonstrates overloading in the constructor and bark
method of the Dog class:
public class Dog
{
Float m_height, m_weight;
StringBuffer m_breed;
}
Dog()
{
m_height=0;
m_weight=0;
m_breed = null;
}
Dog(float height, float weight, String breed)
{
m_height= height;
m_weight= weight;
m_breed = new StringBuffer(breed);
}
void bark()
{
//Plays default bark sound file.
}
void bark(int tone, float sec)
{
//Plays bark sound of given tone and durration.
}
Because a call to an overloaded method is resolved at compile time,
method overloading is also sometimes referred to as static polymorphism.
 Frank Koch
38
Method Overriding
Method overriding is used to elicit different behaviors from objects related by an
inheritance hierarchy. To support polymorphism through overriding, the following
two conditions must exist:
•
An inheritance relationship must exist between two or more classes.
•
A similar method must be implemented in both the super class and one or more
of its subclasses. The method must have a consistent signature — name, return
type, and parameter list — in all classes.
public class Mammal
{
boolean m_isAsleep;
void sleep(boolean b)
{
m_isAsleep = b;
}
}
public class Dog extends Mammal
{
boolean m_isOnGuard;
void sleep(boolean b)
{
//Dog sleeps if not on guard duty and b == true.
if (m_isOnGuard == false)
super.sleep(b);
}
}
Note the use of the super keyword in the subclass to invoke its parent class version of the same method. Even though overriding normally hides the super class's
version of a method, the super keyword can be used to force access to it from
within the subclass. Now that the sleep method has been properly overridden, it
can be invoked through a reference to the base class, as shown in the following
code:
Mammal mam1 = new Mammal(), dog1 = new Dog();
mam1.sleep();
//calls Mammal.sleep
dog1.sleep();
//calls Dog.sleep polymorphically
Although the variable dog1 has the data type of Mammal, the call to sleep invokes
the proper method Dog.sleep, because it really references a Dog object.
Because a call to an overridden method may be resolved at run time, method
overriding is also sometimes referred to as dynamic polymorphism.
 Frank Koch
39
Garbage Collection
Java führt selbständig eine Garbage Collection durch und entlastet den Programmierer damit von der Notwendigkeit, Objekte explizit freizugeben.
Die Garbage Collection arbeitet weitgehend autark. Je nach Auslastung des Speichers wird diese Komponete aktiv und sucht Objekte, die nicht mehr referenziert
werden und damit defacto nutzlos geworden sind. Der von solchen Objekten belegte Speicherplatz wird zurückgewonnen und kann von neuen Objekten genutzt werden. Zur Aktivierung der Garbage Collection kommt es in der Regel, wenn die
Speicherverwaltung einen Speicherengpass vorhersieht. So können Programme
mit geringem Speicherbedarf ablaufen, ohne je die Garbage Collection benötigt zu
haben.1 Bevor die Garbage Collection den Speicher eines Objektes zurüchgewinnt,
wird die finalize()-Methode dieses Objektes aufgerufen (sofern diese Methode existiert).
Mit System.gc() können Sie die Garbage Collection auch explizit aufrufen. Dies gilt
als ‚Vorschlag‘ an die Java Virtual Machine, unbenutzte Objekte zu recyclen. Ob
die Garbage Collection dann wirklich alle nichtreferenzierte Objekte zurückgewinnt,
hängt von den Laufzeitbedingungen des konkreten Falls ab.
Wenn Sie ein Objekt nicht mehr benötigen, hören Sie einfach auf, es zu referenzieren. Dazu kann seine Referenz auf ein anderes Objekt oder auf null gerichtet werden, oder aber eine Methode wird abgeschlossen, so dass lokale Referenzvariablen ihre Gültigkeit verlieren.
Das folgende Pgm ist so angelegt, dass in einer for-Schlaufe sehr viele Objekte
erzeugt werden. Dadurch erreicht das kleine Pgm einen hohen Speicherbedarf.
Immer dann, wenn l auf ein neues Line-Objekt gesetzt wird, verliert sich die Referenz auf das alte Line-Objekt. Läuft die Schleife nur wenige Male (z.B. 100 mal),
so kann es sein, dass die Garbage Collection nie aufgerufen wird. Läuft die Schleife hingegen viele Male, so muss die Garbage Collection den durch die nicht mehr
benötigten Objekte belegten Speicherplatz wiedergewinnen. Auf meinem Rechner
wird die Garbage Collection im Fall von 10000 Schleifendurchläufen 7928 mal aktiv.
class Line
{
static int callFinalize = 0;
Point m_a, m_b;
public Line() {
m_a = new Point(0,0); m_b = new Point(0,0);
}
public void finalize() {
callFinalize++;
}
public static void main (String[] args ) {
Line l;
for(int i = 0; i < 10000; i++)
l = new Line(); // loosing object references
System.out.println("Calls: " + callFinalize);
}
}
•
1
Quelle: Ken Arnolds & James Gosling, „Java Die Programmiersprache“
 Frank Koch
40
Object Wrappers
Mit Ausnahme der primitiven Datentypen (byte, short, int, long, float,
double, char und boolean) sind alle Java-Strukturen immer Objekte.
Manchmal möchte man, dass sich auch die primitiven Datentypen wie
Objekte verhalten, denn dann kann man von deren Methoden profitieren
(z.B. konvertieren des Wertes). Aus diesem Grunde kennt Java sogenannte ObjectWrappers für alle primitiven Datentypen.
Man erkennt ein ObjectWrapper-Object daran, dass der Datentyp gross
geschrieben wird. Natürlich muss nun wieder Speicher alloziert werden.
Definition von Object Wrapper Objekten
Float f = new Float();
Integer i = new Integer();
intObj wird mit der Integer-Repräsentation von 4711 initialisiert
Integer intObj = new Integer("4711");
der in intObj gespeicherte Wert wird i zugewiesen
int i = intObj.intValue();
der in intObj gespeicherte Wert wird str zugewiesen
String str = intObj.toString();
Merke:
Mit den in ObjectWrappers gespeicherten Werten kann keine Arithmetik
betrieben werden. intObj++ ist also nicht möglich.
 Frank Koch
41
Übung Wiederverwendung
Erstellen Sie ein Java-Programm mit mehreren Klassen
gemäss der folgenden Spezifikation:
Klassenname
Mensch
Lebewesen
• Daten
• iq
• herz
• Methoden
•
•
•
•
•
setIq
getIq
verlieben
pgmieren
print
• setHerz
• getHerz
• print
Ehe
• frau
• mann
• ehejahre
•
•
•
•
setFrau
getFrau
...
print
Probieren Sie dabei die "Besteht aus"- sowie die "Ist
ein"-Beziehung. Integrieren Sie möglichst alle im Unterricht angesprochenen Konzepte (Method Overloading,
Method Overriding, Standardkonstruktor, super, finalize, static, ...).
 Frank Koch
42
Passing Params to an Application
When you declare a main method for a Java application, you
must specify an array of strings as a parameter. This array
stores parameters from the user when the program is executed from the command line. You access a specific array
element by specifying the index to the array:
public class Hello
{
public static void main(String args[])
{
System.out.println("Hello " + args[0]+"!");
}
}
You can pass parameters to a Java application by typing in
arguments at the command line: java Hello Peter
The output is: Hello Peter!
To determine the number of arguments passed from the
command line, use the length property of the args[ ] array.
 Frank Koch
43
Passing Params to an Applet
Applets get parameters by using a special parameter tag in
the HTML file called the PARAM tag. Each PARAM tag has
two attributes: NAME and VALUE.
<APPLET
CODE="Hello.class"
WIDTH=300
HEIGHT=300>
<PARAM NAME="Vorname" VALUE="James">
<PARAM NAME="Nachname" VALUE="Gosling">
</APPLET>
Your Java applet then uses a getParameter method to process parameters. This method takes an argument representing
the name of the parameter passed to it.
The following code shows how to obtain the parameters
passed in through an HTML file:
String vorname = getParameter("Vorname");
String nachname = getParameter("Nachname");
If the NAME parameter is omitted in the HTML file, the getParameter method returns null. It is recommended that you
verify that a value is returned from getParameter. If you attempt to access a method or property of the String object that
is equal to null, your code will generate a NullPointerException exception. You can verify that getParameter returns a
value by checking for null, as shown here:
if (vorname == null) {
showStatus("No name specified");
System.exit(0);
}
 Frank Koch
44
Übung Passing Params to an Applet
Ein Applet soll den aus einem HTML-File übergebenen
Text (z.B. "Wir lernen Java") ausgeben.
Erstellen Sie das Applet ParamApplet.java mit der
Klasse ParamApplet sowie die Datei ParamApplet.html.
Ihr Applet soll eine Fehlermeldung generieren, wenn
der Text nicht oder nicht richtig spezifiziert wurde.
Die Lösung finden Sie im Anhang.
 Frank Koch
45
Anhang:
Lösung Passing Params to an Applet
ParamApplet.java
import java.applet.Applet;
import java.awt.Graphics;
public class ParamApplet extends Applet {
public void paint(Graphics g) {
String text = getParameter("Text");
if (text == null) {
showStatus("No text specified");
System.exit(0);
}
g.drawString("Der Text \"" + text +
"\" wurde übergeben", 20, 40);
}
}
ParamApplet.html
<HTML>
<HEAD>
<TITLE> A Simple Program </TITLE>
</HEAD>
<BODY>
<APPLET
CODE="ParamApplet.class"
WIDTH=300
HEIGHT=100>
<PARAM NAME="Text" VALUE="Wir lernen Java">
</APPLET>
</BODY>
</HTML>
 Frank Koch
46
Exception Handling - Ausgangslage
class Point
{
private static int s_no;
public int m_x, m_y;
public Point(int x, int y) {
s_no++;
setX(x);
setY(y);
}
public void finalize() {s_no--;}
public void setX(int x) {
if (x<0)
m_x = 0;
System.out.println("X: Falscher Wert
System.exit(0);
else {
m_x = x;
}
}
public void setY(int y) {
if (y<0)
m_y = 0;
System.out.println("Y: Falscher Wert
System.exit(0);
else {
m_y = y;
}
}
public int getX() {return m_x;}
public int getY() {return m_y;}
public void print() {
System.out.println(m_x + " " + m_y);
}
public static void printNo() {
System.out.println("Anzahl: " + s_no);
}
public static void main (String[] args ) {
Point a=new Point(1,-1);
//
Point b=new Point(2,2);
Point c=new Point(3,3);
c.setX(-2);
//
c.setY(-3);
//
a.print(); b.print(); c.print();
Point.printNo();
}
}
 Frank Koch
" + x);
" + y);
Fehler
Fehler
Fehler
47
Exception Handling Syntax
Exception Class
class XException extends Exception
{
XException (Point p, int i) {
super("X: Falscher Wert " + i);
p.m_x=0;
}
}
throws - Klausel
public void setX(int x) throws XException {...}
Auslösen von Exceptions
if (x < 0)
throw new XException(this, x);
Auffangen von Exceptions
public Point(int x, int y) {
...
try {
setX(x);
setY(y);
}
...
catch(XException e) {
System.out.println(e.getMessage());
}
catch(YException e) {
System.out.println(e.getMessage());
}
finally {
// Endbehandlung
}
}
 Frank Koch
48
Exception Handling finally{...}
finally{} wird generell für Aufräumarbeiten (Schliessen von Dateien, Freigeben von Ressourcen , etc.) nach try{} benutzt.
Nützlich daran ist, dass der Code im finally{} garantiert ausgeführt wird unabhängig davon, was im zugehörigen try{} passiert ist.
Im Normalfall wird das Ende des try{} erreicht und anschliessend finally{} ausgeführt.
Falls try{} mit return, continue oder break verlassen wird, wird
zunächst finally{} ausgeführt, bevor der Programmablauf an
der neuen Destination weiterschreitet.
Falls in try{} eine Exception geworfen wird, so wird (falls vorhanden) das lokale catch{} ausgeführt und anschliessend finally{} ausgeführt. Gibt es kein lokales catch{}, so wird zunächst finally{} ausgeführt und anschliessend das nächste
catch{} gesucht, dass die Exception bedienen kann.
Wird innerhalb eines finally{} ein return, continue oder break
ausgeführt oder eine Exception geworfen, so wird ein evtl.
vorher ausgelöster Progammunterbruch ignoriert und der neue
Programmunterbruch sofort behandelt.
 Frank Koch
49
Exception Handling Bsp 1 (1/2)
class XException extends Exception
{
XException (Point p, int wert) {
super("X: Falscher Wert " + wert);
p.m_x = 0; // m_x ist PUBLIC
}
}
class YException extends Exception
{
YException (Point p, int wert) {
super("Y: Falscher Wert " + wert);
p.m_y=0; // m_y ist PUBLIC
}
}
class Point {
static int s_no;
public int m_x, m_y;
public Point(int x, int y) {
s_no++;
try {
setX(x);
setY(y);
}
catch(XException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
catch(YException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public void finalize() {s_no--;}
public void setX(int x) throws XException {
if (x<0)
throw new XException(this, x);
else
m_x = x;
}
 Frank Koch
50
Exception Handling Bsp 1 (2/2)
public void setY(int y) throws YException {
if (y<0)
throw new YException(this, y);
else
m_y = y;
}
public int getX() {return m_x;}
public int getY() {return m_y;}
public void print() {
System.out.println(m_x + " " + m_y);
}
public static void printNo() {
System.out.println("Anzahl: " + s_no);
}
public static void main (String[] args ) {
Point a=new Point(1,-1);
// Fehler
Point b=new Point(2,2);
Point c=new Point(3,3);
try {
c.setX(-2);
// Fehler
c.setY(-3);
// Fehler
}
catch(XException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
catch(YException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
finally {
a.print(); b.print(); c.print();
Point.printNo();
}
Point.printNo();
}
}
 Frank Koch
51
Exception Handling Beispiel 2
Unchecked Exceptions
class UncheckedException
{
public static void main (String[] args ) {
int[] pentagon = new int[5];
try {
int i = 4711;
i = i / 0;
// Fehler
Division by zero
for(i=0; i<pentagon.length; i++) {
pentagon[i] = i;
}
pentagon[i] = 5; // Fehler i = 5
}
}
}
catch (Exception e) {
System.out.println("Threw a " +
e.getClass() +
" with message: " + $
e.getMessage());
}
Resultate (das Pgm wird nach der 1. Exception abgebrochen, weshalb
es nicht zur 2. Ausgabe kommt):
Threw a class java.lang.ArithmeticException with messsage: / by zero
Threw a class java.lang.ArrayIndexOutOfBoundsException with messsage: null
 Frank Koch
52
Interfaces - Definition
Interfaces ähneln Klassen. Während aber eine Klasse die (nicht abstrakten) Methoden implementiert, werden Methoden (sowie Konstanten) in Interfaces nur deklariert. Implementiert eine Klasse das Interface, so können die deklarierten Methoden von ihr unterstützt werden.
interface Lookup {
Object find(String name);
}
Das Interface Lookup definiert eine Methode find(), ohne deren Implementierung anzugeben. Programme, die Referenzen zu LookupObjekten nutzen, können find() aufrufen, wobei der tatsächliche Typ
des Objekts keine Rolle spielt.
void test(String name, Lookup array) {
Object o = array.find(name);
}
Nachfolgend sehen wir die Implementierung eines Interfaces.
class MyLookup implements Lookup {
private String[] names;
private Object[] values;
public Object find(String name) {
for(int i = 0; i < names.length; i++)
if (names[i].equals(name))
return values[i];
return null;
}
}
Auch Interfaces können mit extends erweitert werden. Ein Interface
kann ein oder mehrere andere Interfaces erweitern. Die Menge der Basistypen einer Klasse besteht aus der von ihr erweiterten Klasse (extends) und den von ihr implementierten Interfaces (implements) einschliesslich aller Basistypen dieser Klasse und dieser Interfaces.
Ein Interface kann von vielen Klassen implementiert werden, wobei
sich die Implementierungen in den vom Interface-Programmierer bestimmten Grenzen (Methoden-Signatur) unterscheiden können. Interfaces bieten damit die Möglichkeit ein Mindestverhalten ihrer Implementierungen zu garantieren.
 Frank Koch
53
Interfaces - Mehrfachvererbung
In Java kann eine Klasse nur aus einer Klasse abgeleitet werden (single
inheritance). Oft aber gibt es Situationen, in denen eine Klasse EigenFahrzeug
schaften von mehreren Klassen erben
sollte (ein Luftkissenboot ist ein LandLandfahrzeug
Wasserfahrzeug
sowie ein Wasserfahrzeug). Nun
könnte man versucht sein, die in
Luftkissenboot
Land- und Wasserfahrzeugen implementierten Eigenschaften stattdessen
in deren Parentklasse Fahrzeuge anzusiedeln und das Luftkissenboot
daraus abzuleiten. Schnell ginge man höher und höher und würde
letztendlich die Klasse Object auf unbewältigbare Proportionen anwachsen lassen.
Object
Java unterstützt multiple inheritance bei Interfaces, So können wir, anstatt Eigenschaften zu Object hinzuzufügen, diese in einem Interface
ansideln. Interfaces in der Klassenhierarchie geben Java damit die
Möglichkeit der Mehrfachvererbung.
interface FZ { // FZ = Fahrzeug
public void movePos(int x, int y);
}
interface LandFZ extends FZ {
public void park();
}
interface WasserFZ extends FZ {
public void sink();
}
class Luftkissenboot implements LandFZ, WasserFZ {
int m_x, m_y;
boolean m_park=false, m_sink=false;
public void movePos(int x, int y) {
m_x = x; m_y = y;
}
public void park(){
m_park = true;
}
public void sink(){
m_sink = true;
}
}
 Frank Koch
54
Interfaces - Weiteres
Alle Methoden in einem Interface sind implizit abstrakt. Weil ein Interface Implementierungen ihrer deklarierten Methoden nicht bereitstellen
muss, braucht es diese Methoden auch nicht als abstrakt zu deklarieren. Jede ein Interface implementierende Klasse muss entweder alle
ihre Methoden oder alternativ nur einige ihrer Methoden implementieren. In letzterem Fall ist die Klasse dann abstrakt und muss auch so
deklariert werden. Methoden in einem Interface sind stets public.
Die Methoden in einem Interface können nicht static (klassenbezogen)
sein, da als static deklarierte Methoden immer klassenbezogen und
damit konkret statt abstrakt sind und ein Interface nur abstrakte Methoden enthalten kann.
Die Variablen eines Interfaces hingegen sind immer static (klassenbezogen) und final (endgültig). Sie dienen der Definition von beim Aufruf
von Methoden verwendeten Konstanten.
interface FZ { // FZ = Fahrzeug
static final int INITIAL_X_POS = 0;
static final int INITIAL_Y_POS = 0;
public void movePos(int x, int y);
}
...
public void park(){
m_x = INITIAL_X_POS;
m_y = INITIAL_Y_POS;
m_park = true;
}
 Frank Koch
55
Übung
Erstellen Sie den Code zu folgendem Diagramm (Interfaces sind
schraffiert, Klassen nicht-schraffiert gekennzeichnet).
Fahrzeug
Landfahrzeug
Wasserfahrzeug
Transporter
PersonenTransporter
Luftkissenboot
Verteilen Sie die folgende Funktionalität in sinnvoller Weise an den adäquaten Stellen im obigen Diagramm. Beschränken Sie sich auf das
Wesentlichste.
• Ein Luftkissenboot kann parken, sinken, sowie sich fortbewegen.
• Die Transportfähigkeit eines Luftkissenbootes lässt sich mit dem
Transportgewicht sowie der Anzahl beförderbarer Personen beschreiben.
• Ein Luftkissenboot verfügt über die Methode status(), mit der es alle
in ihm vorhandenen Variablen auf dem Bildschirm ausgibt.
• Zum Schluss benötigen wir noch eine main()-Methode, mit der wir
ein konkretes Luftkissenboot mit bestimmtem Transportgewicht sowie bestimmter Anzahl Personen erzeugen, es an eine neue Position versetzen und es dort parken. Danach ruft main() die Methode
status() auf.
 Frank Koch
56
Anhang: Lösung Interface
interface FZ { // FZ = Fahrzeug
int INITIAL_X_POS = 0;
int INITIAL_Y_POS = 0;
public void movePos(int x, int y);
}
interface LandFZ extends FZ {
public void park();
}
interface WasserFZ extends FZ {
public void sink();
}
class Transporter {
int m_transportGewicht;
public void setTransportGewicht(int tg) {
m_transportGewicht = tg;
}
public int getTransportGewicht() {
return m_transportGewicht;
}
}
class PersonenTransporter extends Transporter {
int m_anzahlPersonen;
public void setAnzahlPersonen(int ap) {
m_anzahlPersonen = ap;
}
public int getAnzahlPersonen() {
return m_anzahlPersonen;
}
}
class Luftkissenboot extends PersonenTransporter
implements LandFZ, WasserFZ {
int m_x, m_y;
boolean m_park=false, m_sink=false;
public void movePos(int x, int y) {
m_x = x; m_y = y;
}
public void park(){
m_x = INITIAL_X_POS;
m_y = INITIAL_Y_POS;
m_park = true;
}
public void sink(){
m_sink = true;
}
public void status () {
System.out.println("Transportgewicht = " +
m_transportGewicht);
System.out.println("AnzahlPersonen = " + m_anzahlPersonen);
System.out.println("Park = " + m_park);
System.out.println("Sink = " + m_sink);
}
public static void main (String[] args ) {
Luftkissenboot lkb =new Luftkissenboot();
lkb.setTransportGewicht(6000);
lkb.setAnzahlPersonen(100);
lkb.movePos(10, 10);
lkb.park();
lkb.status();
}
}
 Frank Koch
57
Thread Zustände
Ezeugt
Thread wurde mit new erzeugt und kann nun mit
den für den späteren Ablauf notwendigen Daten
initialisiert werden.
Ablauffähig Diesen Zustand erreicht der Thread durch den
Aufruf der Thread-Methode start(). Der Thread
wird damit rechenbereit und kann von dem JavaLaufzeitsystem (Java-Scheduler) in den Zustand
rechnend überführt werden. Der Java-Scheduler
bestimmt nach einem Prioritäten- und RoundRobin-Verfahren den nächsten Thread, der den
Prozessor belegen darf.
Rechnend Diesen Zustand erreicht der Thread durch den
Aufruf der Thread-Methode run() durch den Java-Scheduler. Hier wird die eigentliche Arbeit
verrichtet, weshalb die run()-Methode in der abgeleitetenKlasse redefiniert werden muss.
Beendet
Ist die run()-Methode abgearbeitet oder wurde
die stop()-Methode des Threads aufgerufen, so
befindet sich der Thread in dem Zustand beendet. Der Thread könnte nun mit der Methode
start() neu angestossen werden.
Wartend
Hat der Java-Scheduler einen Thread anhalten,
so ist dieser "wartend". Dies kann durch mehrere
Methoden erreicht werden:
• Methode sleep(long millisec)
Der Thread wird für die angegebene Zeitspanne auf "wartend" gesetzt und danach automatisch auf "ablauffähig" gesetzt.
• Methode suspend()
Der Thread wird auf "wartend" gesetzt und
wird erst wieder durch die Methode resume()
auf "ablauffähig" gesetzt.
• Methode yield()
Thread gibt den Prozessor freiwillig frei und
wird auf "ablauffähig" gesetzt. Dies kann die
 Frank Koch
58
Performance anderer Threads steigern.
 Frank Koch
59
Thread Beispiel
class PingPong extends Thread
{
String m_word;
long m_delay;
public PingPong(String word) {
m_word = word;
}
public void start()
{
System.out.println("Thread started");
super.start();
}
public void run()
{
try {
while(true) {
System.out.print(m_word+" ");
// Pseudozufallszahl 0..100 gleichverteilt
m_delay = (long)(Math.random()*100);
// Nachfolgend 3 Alternativen
// eine geerbte Methode aufzurufen
Thread.sleep(m_delay);
sleep(m_delay);
super.sleep(m_delay);
}
}
catch(InterruptedException e) {return;}
}
public static void main(String[] args)
{
// 1. Art Objekt zu instanziieren
PingPong ping = new PingPong("ping");
ping.start();
}
}
// 2. Art Objekt (ohne Namen) zu instanziieren
new PingPong("PONG").start();
Resultat:
Thread started
ping ping ping ping ping ping ping ping ping ping ping ping ping ping ping ping ping ping
ping ping ping Thread started
PONG PONG ping PONG ping PONG PONG ping ping PONG PONG PONG ping ping PONG
PONG ping PONG PONG ping PONG PONG PONG ping PONG ping ping ping PONG ping
 Frank Koch
60
Thread mit und ohne synchronize
class Lager
{
private long m_bestand;
public Lager(long menge) {m_bestand = menge;}
public /*synchronized*/ void trx(long menge, int no) {
System.out.print("[" + no);
long tmp = m_bestand + menge;
for(long i=0; i<500000; i++); // Zeitverschwendung...
m_bestand = tmp;
System.out.print(no + "] ");
}
public long getMenge() {return m_bestand;}
}
class Handel extends Thread
{
private static Lager m_birnen = new Lager(100); // nur ein Lager!
private static int m_anzahlThreads = 0;
private int m_threadNummer;
}
public Handel() {}
public void start() {
System.out.println("Thread started");
m_threadNummer = m_anzahlThreads ++;
super.start();
}
public void run() {
while(true) {
m_birnen.trx((long)(Math.random()*100), m_threadNummer);
try {
sleep((long)(Math.random()*10));
}
catch(InterruptedException e) {
return;
}
}
}
public static void main(String[] args) {
new Handel().start();
new Handel().start();
new Handel().start();
}
Ohne synchronize
Thread started
Thread started
[0Thread started
0] [1[2[02] 0] [22] 1] [2[1[01] 2] 0] [1[01] [2[11] 2] 0] [2[1[02] 0] 1] [22] [0
[1[22] 1] 0] [1[2[00] 1] [0[12] 1] [1[20] 1] [02] [1[20] 1] 2] [0[1[20] 2] [01]
Mit synchronize
Thread started
Thread started
Thread started
[00] [22] [11] [00] [22] [11] [00] [22] [11] [00] [22] [00] [11] [00] [22] [00]
[11] [22] [00] [11] [22] [00] [11] [00] [22] [11] [00] [22] [11] [22] [00] [11]
 Frank Koch
61
wait() und notify()
Die Methoden wait() und notify() sind in der Klasse Object definiert und
werden von allen Klassen geerbt. Sie werden wie Sperren auf bestimmte
Objekte angewendet. Mait wait() wartet man auf ein bestimmtes Ereignis, dass an anderer Stelle mit notify() erzeugt wird.
Alles wird innerhalb einer synchronize-Methode durchgeführt. Andernfalls wäre der Inhalt des Objekts nicht stabil.
wait()
synchronize checkCondition() {
while(!condition)
wait()
// Code für den Erfüllungsfall der Bedingung
}
wait() setzt die Methode in einen Wartezustand. Gleichzeitig wird die
synchronize-Sperre aufgehoben, so dass die Methode wieder von anderen Threads benutzt werden kann.
notify()
synchronize changeCondition() {
// Ändern der für die Bedingung relevanten Werte
notify()
}
Mehrerer Threads können auf dasselbe Objekt warten. Ein Aufruf von
notify() weckt den am längsten Wartenden auf. Sollen alle Threads aufgeweckt wreden, kann notifyAll() benutzt werden.
 Frank Koch
62
Kommunikation zwischen Threads
class Lager
{
private long m_bestand;
public Lager(long menge) {m_bestand = menge;}
public synchronized void trx(long menge, int no) {
long tmp = m_bestand + menge;
for(long i=0; i<500000; i++); // Zeitverschwendung...
m_bestand = tmp;
//notify();
}
public synchronized long getMenge() {
//try {wait();}
//catch(InterruptedException e) {return (long)0;}
return m_bestand;
}
}
class Handel extends Thread
{
private static Lager m_birnen = new Lager(100); // nur ein Lager!
private static int m_anzahlThreads = 0;
private int m_threadNummer;
}
public Handel() {}
public void start() {
System.out.println("Thread started");
m_threadNummer = m_anzahlThreads++;
super.start();
}
public void run() {
while(true) {
if (m_threadNummer == 0)
System.out.print(m_birnen.getMenge() + " ");
else {
m_birnen.trx((long)(Math.random()*100),
m_threadNummer);
try {
sleep((long)(Math.random()*10000));
}
catch(InterruptedException e) {
return;
}
}
}
}
public static void main(String[] args) {
new Handel().start();
new Handel().start();
new Handel().start();
}
Ohne wait() und notify()
Thread started
Thread started
Thread started
100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 132 132 132 132 132 132 132 132 132 132 132 132 132 132
Mit wait() und notify()
Thread started
Thread started
Thread started
 Frank Koch
63
230 240 267 290 387 412 432 440 489 500 597 601 646 675 720 805 843 888 912 954
 Frank Koch
64
Interface Runnable
Leiten wir eine Klasse aus Thread ab, dann können wir diese nicht gleichzeitig aus
anderen Klassen ableiten. Deshalb implementiert die Klasse Thread das Interface
Runnable. Das Interface Runnable deklariert eine einzige Methode:
public void run();
Wird ein Thread-Objekt mit Hilfe eines Objekts vom Typ Runnable erzeugt, ruft die
Implementierung von Thread.run() die Methode run() des Runnable-Objekts auf.
class RunPingPong implements Runnable
{
String m_word;
int m_delay;
RunPingPong(String word, int delay)
{m_word = word; m_delay = delay;}
public void run()
{
try {
while(true)
{
System.out.print(m_word+" ");
Thread.sleep(m_delay);
}
}
catch(InterruptedException e)
{return;}
}
}
public static void main(String[] args)
{
RunPingPong ping = new RunPingPong("ping", 33);
RunPingPong pong = new RunPingPong("PONG", 55);
new Thread(ping).start();
new Thread(pong).start();
}
Resultat:
ping PONG ping ping PONG ping ping PONG ping ping PONG ping PONG ping ping PONG
ping ping PONG ping PONG ping ping PONG ping PONG ping ping PONG ping PONG ping
Ein Runnable-Objekt kann in seiner eigenen Thread-Umgebung ausgeführt werden.
Dazu wird ein Thread-Objekt angelegt z.B. mit
new Thread(<object>).start();
Der Thread wird dabei mit der run()-Methode des Objekts verbunden. Ein so konstruiertes Thread-Objekt ruft dann beim Starten genau diese im eigentlichen Anwendungsobjekt realisierte run()-Methode auf.
 Frank Koch
65
Übung Queue
Erstellen Sie einen Puffer mit begrenzter Anzahl Elementen (z.B. int-Array mit 10 Elementen). Eine Erzeuger-Thread legt darin Datenelemente (Zahlen) an. Eine
Verbraucher-Thread nimmt Daten aus diesem PufferBereich heraus und verarbeitet diese (Ausgabe auf
dem Bildschirm).
Ist der Puffer voll, so muss die Erzeuger-Thread pausieren. Ist der Puffer leer, so muss die VerbraucherThread pausieren.
Interessant wird es, wenn Sie mehrere Erzeuger- und
Verbraucher-Threads instanziieren... Probieren Sie
auch Varianten mit unterschiedlich langen Pufferbereichen...
Sie zweifeln an der betriebswirtschaftlichen Relevanz
dieser Übung? Dann ersetzen Sie doch die Zahlen
durch Hamburger, die Verbraucher durch HamburgerEsser und die Erzeuger durch McDonald-Personal ☺
Die Lösung finden Sie im Anhang.
 Frank Koch
66
Anhang: Lösung Queue (1/2)
class Erzeuger extends Thread
{
String m_name;
int m_delay;
}
Erzeuger(String name) {m_name=name;}
public void run() {
try {
while(true) {
m_delay = (int)(Math.random()*800);
System.out.print(m_name + " : ");
if (!Queue.eingabe((int)(Math.random()*300))) {
System.out.println("Puffer voll");
sleep(2000);
}
else sleep(m_delay);
}
}
catch (InterruptedException e) {return;}
}
class Verbraucher extends Thread
{
String m_name;
int m_delay;
Verbraucher(String name) {m_name=name;}
public void run() {
try {
while(true) {
m_delay = (int)(Math.random()*800);
System.out.print(m_name + " : ");
if (!Queue.ausgabe()) {
System.out.println("Puffer leer");
sleep(2000);
}
else sleep(m_delay);
}
}
catch (InterruptedException e) {return;}
}
}
 Frank Koch
67
Anhang: Lösung Queue (2/2)
class Queue
{
static int[] m_menge = new int[10];
static int m_zaehler = 0;
synchronized public static boolean eingabe(int neu) {
if (m_zaehler < m_menge.length) {
m_menge[m_zaehler++]=neu;
System.out.println("Eingabe: " + m_menge[m_zaehler-1]);
return true;
}
else return false;
}
synchronized public static boolean ausgabe() {
if (m_zaehler > 0) {
System.out.println("Ausgabe: " + m_menge[--m_zaehler]);
return true;
}
else return false;
}
public static void main(String[] args)
{
new Erzeuger("Erzeuger1
").start();
new Erzeuger("Erzeuger2
").start();
new Verbraucher("Verbraucher1").start();
new Verbraucher("Verbraucher2").start();
}
}
 Frank Koch
68
Packages 1
Packages sind Sammlungen logisch zueinander gehörender Klassen und Interfaces.
Bei der Benutzung einer Klasse muss deren Package-Name angeben werden, womit
auch bei einer hohen Zahl von Klassen jede einen eindeutigen Namen hat.
Jede Klasse gehört zu einem Package und wird mit dem Kompilieren ihrem Package
zugefügt. Wird keine package-Anweisung benutzt, so wird die Klasse dem DefaultPackage zugefügt, das Unnamed Package genannt wird.
File ComplexNumber.java
Package srd.math;
public class ComplexNumber
{
private double m_real;
private double m_imag;
public ComplexNumber(double real, double imag) {
m_real = real; m_imag = imag;
}
public ComplexNumber Add(ComplexNumber c) {
return new ComplexNumber(m_real+c.m_real, m_imag+c.m_imag);
}
}
File Test.java
class Test
{
public static void main(String[] args) {
srd.math.ComplexNumber c1, c2;
c1 = new srd.math.ComplexNumber(1.0, 1.0);
c2 = new srd.math.ComplexNumber(2.0, 2.0);
srd.math.ComplexNumber c3 = c1.Add(c2);
}
}
... oder besser so ...
import srd.math.ComplexNumber;
class Test
{
public static void main(String[] args) {
ComplexNumber c1, c2;
c1 = new ComplexNumber(1.0, 1.0);
c2 = new ComplexNumber(2.0, 2.0);
ComplexNumber c3 = c1.Add(c2);
}
}
Packages und das File System
• Besteht ein Sourcefile aus mehr als einer Klassen, so darf nur eine Klasse public deklariert sein
und das Sourcefile muss den gleichen Namen wie diese Klasse tragen.
• .class-files werden in einem Verzeichnis gespeichert, dessen Namenskomponenten zu den Namenskomponenten des Pakets korrespondieren. So werden die .class-files zu dem Paket
ch.zhwin.kfr.games unter %CLASSPATH%\ch\zhwin\kfr\games\* gespeichert. Im obigen Bsp wird
die Klasse ComplexNumber unter .\srd\math\ComplexNumber gespeichert.
• Java-Code ohne package-Anweisung wird automatisch dem unnamed package zugeordnet.
• Klassen, die public deklariert sind, sind von ausserhalb und innerhalb eines Pakets zugreifbar.
• Klassen, die nicht public deklariert sind, sind nur von innerhalb eines Pakets zugreifbar.
• Compilieren Sie die zu einem Paket gehörenden Sourcefiles und trasferieren Sie die generierten
.class-files anschliessend in das korrespondierende Verzeichnis. Anschliessend können Sie die
so organisierten Klassen über die import-Anweisung benutzen.
• Die import Anweisung kann für jede Klasse komplett ausgeschrieben werden (z.B. import
zhwin.kfr.OnePublic). Oder aber Sie wird abgekürzt (z.B. import zhwin.*). Im Abkürzungsfall darf
 Frank Koch
69
sich der zum Paket gehörende Source nicht in dem Entwicklungsverzeichnis befinden. Im komplett ausgeschriebenen Fall gilt diese Restriktion nicht.
 Frank Koch
70
Packages 2
//.OnePublic.java
//.\zhwin\kfr\OnePublic.class
package zhwin.fkoch;
//.TwoPublic.java
//.\zhwin\kfr\TwoPublic.class
package zhwin.fkoch;
public class OnePublic {
public void m_public() {}
private void m_private() {}
void m_friendly() {}
public static void main(String[] args) {
One o = new One();
o.m_public();
//o.m_private(); nicht ok
o.m_friendly();
}
}
public class TwoPublic {
public void m_public() {}
private void m_private() {}
void m_friendly() {}
public static void main(String[] args) {
OnePublic op = new OnePublic();
One o = new One();
}
}
class One {
public void m_public() {}
private void m_private() {}
void m_friendly() {}
public static void main(String[] args) {
OnePublic op = new OnePublic();
op.m_public();
//op.m_private(); nicht ok
op.m_friendly();
}
class Two {
public void m_public() {}
private void m_private() {}
void m_friendly() {}
public static void main(String[] args) {
OnePublic op = new OnePublic();
One o = new One();
}
}
Package: zhwin.fkoch
//.\ZhwinTest.java
//.\ZhwinTest.class
//Paket-Source darf nicht im Verzeichnis '.' sein
import zhwin.kfr.*;
//Alternativ:
//Paket-Source darf nun im Verzeichnis '.' sein
//import zhwin.kfr.OnePublic;
//import zhwin.kfr.TwoPublic;
class ZhwinTest
{
public static void main(String[] args) {
OnePublic op = new OnePublic();
op.m_public();
//op.m_private(); nicht ok
//op.m_friendly(); nicht ok
//One o = new One();
nicht ok
TwoPublic tp = new TwoPublic();
}
 Frank Koch
71
Java Core Packages
Java beinhaltet 6 Core-Packages. In jedem Paket sind die Klassen in einer Hierarchie geordnet, d.h. Klassen auf niedriger Stufe erben von ihren Superklassen.
java.lang
java.io
java.util
java.net
java.awt
java.applet
Definiert Datentypen, Objekte, WrapperClasses, Klassen für Prozesse und die Runtime-Umgebung, Unterstützung für Multithreading
Klassen und Interfaces für I/O: Files, Streams, Filter, Exceptions
DataCollection-Klasses (z.B. Stack), Utility-Classes
(z.B.Random)
Network-Communication using TCP/IP, UDP, HTTP,
URL, Sockets, Datagram-Class
Steht für Abstract Windowing Toolkit und stellt viele
Klassen für das GUI zur Verfügung. Graphic, GUIElemente, Container, Menus)
Dieses Package enthält 2 Subpackages:
• java.awt.image: Klassen und Interfaces für ImageData
• java.awt.peer: Für das Mapping von Java-GUI auf das
GUI eines bestimmten Betriebssystems
Um Applets in den Browser zu laden
•
Microsoft hat die Core-Packages zudem um com.ms.com erweitert, um das Zusammenspiel mit COM (Component Object Model) zu ermöglichen. Die Benutzung dieses Packages bedeutet aber, dass Sie Ihre Pgme nur noch auf Plattformen portieren können, die COM unterstützen!
•
Microsoft und Sun sind die grossen Gegenspieler und immer bemüht Allianzen
gegen ihren Gegner zu bilden. MS hat Java von Sun lizensiert und ist damit verpflichtet Visual J++ periodisch den neuen Features der Sprache Java sowie der
Core-Packages anzupassen. Andererseits bemüht sich MS stetig, Java zu seinen
Gunsten zu erweitern und zeigt sich sehr zäh, wenn es darum geht von SUN entwickelte Standards in Java++ zu implementieren. Es gab bereits einige gerichtliche Auseinandersetzungen. Am besten informieren Sie sich auf dem Internet:
• Splash.javasoft.com
• Java.sun.com/devcorner.html
• www.microsoft.com/visualj/indexpgs/press.htm (Was MS in der Presse veröffentlicht)
• www.microsoft.com/java/resource/press.htm (Was die Presse über MS veröffentlicht)
 Frank Koch
72
Utility Package (util)
Date Class
• Liefert Methoden zur Behandlung des Datums
Stack Class
• Stacks sind bekannte Strukturen in der Pgmierung und funktionieren
wie ein Tellerstapel (LIFO).
• Hier arbeitet man mit push und pop
Random Class
• Braucht man für Zufallszahlen
Observable Class
• Die Observable Class erlaubt es einem Objekt ein anderes zu observieren. Ändert sich der Zustand des observierten Objekts, so informiert es seinen Observer.
StringTokenizer Class
• Mit dieser Klasse können Sie Strings parsen. Ein String wird dabei in
Token (Bestandteile des Strings) zerlegt, wobei Sie bestimmen, was
als Delimiter der einzelnen Token gesehen wird.
import java.util.*;
public class ParseString {
public static void main(String args[]) {
String str = "To be or not to be";
String ary[] = new String[10];
StringTokenizer t = new StringTokenizer(str);
for (int i=0;t.hasMoreTokens();i++) {
ary[i]=t.nextToken();
System.out.println(ary[i]);
}
}
}
 Frank Koch
73
Abstract Windowing Toolkit (awt)
Die Entwicklung eines grafischen User-Interfaces, das auf vielen Plattformen läuft, wird durch das Java-AWT-Package ermöglicht. Dieses Package enthält Klassen, mit denen man relativ einfach portable und grafische Benutzeroberflächen realisieren kann.
Das AWT beinhaltet im wesentlichen drei Arten von Klassen:
Kontrollelemente
Erlauben die Interaktion des Benutzers mit der Anwendung (Button, Menue, Dialogbox, ...).
Container
Verwalten Kontrollelemente. Es gibt den Container Frame, welcher einem Window entspricht und den Container Panel, welcher die Gruppierung von Kontrollelementen entspricht.
Layout-Manager
Werden innerhalb von Containern benutzt, um Kontrollelemente automatisch anzuordnen.
Die Klassen im AWT-Package:
Component
Container
Window
Dialog
FileDialog
Frame
Panel
Applet
Button
Canvas
CheckBox
Label
List
Scrollbar
TextComponent
TextArea
TextField
 Frank Koch
74
Container und Layout
import java.awt.*;
class DemoFrame
{
public static void main(String[] args) {
Frame fr = new Frame("FrameDemo");
fr.setSize(400, 400);
fr.setVisible(true);
}
}
class DemoMultipleFrame
{
public static void main(String[] args) {
Frame fr1 = new Frame("MultipleFrameDemo1");
fr1.setSize(200, 600);
fr1.setVisible(true);
Frame fr2 = new Frame("MultipleFrameDemo2");
fr2.setSize(600, 200);
fr2.setVisible(true);
}
}
class DemoBL
{
public static void main(String[] args) {
Frame fr = new Frame("BorderLayoutDemo");
fr.setLayout(new BorderLayout());
fr.add("North", new Button("Eins"));
fr.add("South", new Button("Zwei"));
fr.add("East", new Button("Drei"));
fr.add("West", new Button("Vier"));
fr.add("Center", new Button("Fünf"));
fr.pack();
fr.setVisible(true);
}
}
class DemoFL
{
public static void main(String[] args) {
Frame fr = new Frame("FlowLayoutDemo");
fr.setLayout(new FlowLayout());
fr.add(new Button("Eins"));
fr.add(new Button("Zwei"));
fr.add(new Button("Drei"));
fr.add(new Button("Vier"));
fr.add(new Button("Fünf"));
fr.pack();
fr.setVisible(true);
}
}
class DemoGL
{
public static void main(String[] args) {
Frame fr = new Frame("GridLayoutDemo");
fr.setLayout(new GridLayout(3, 2));
fr.add(new Button("Eins"));
fr.add(new Button("Zwei"));
fr.add(new Button("Drei"));
fr.add(new Button("Vier"));
fr.add(new Button("Fünf"));
fr.pack();
fr.setVisible(true);
}
}
 Frank Koch
75
Panel
Manchmal benötigt man Komponenten innerhalb von Komponenten. Dazu kann die Container-Subklasse Panel eingesetzt werden.
import java.awt.*;
class DemoComplex
{
public static void main(String[] args)
{
// Create FlowLayout Panel
Panel pfl = new Panel();
pfl.setLayout(new FlowLayout());
pfl.add(new Button("Eins"));
pfl.add(new Button("Zwei"));
pfl.add(new Button("Drei"));
// Create BorderLayout Panel
Panel pbl = new Panel();
pbl.setLayout(new BorderLayout());
pbl.add("North", pfl); // Panel within Panel
pbl.add("South", new Button("South"));
pbl.add("Center", new Button("Center"));
}
}
// Create GridLayout Frame
Frame fr = new Frame("ComplexLayoutDemo");
fr.setLayout(new GridLayout(1, 3));
fr.add(pbl);
// Panel within Container
fr.add(new Button("Zwei"));
fr.add(new Button("Drei"));
fr.pack();
fr.setVisible(true);
Ausgabe:
 Frank Koch
76
Menu (MenuDemo.java)
import java.awt.*;
class DemoMenu
{
public static void main(String[] args)
{
Frame fr = new Frame("MenuDemo");
MenuBar mb = new MenuBar();
Menu me = new Menu("English");
me.add(new MenuItem("One"));
me.add(new MenuItem("Two"));
mb.add(me);
Menu md = new Menu("Deutsch");
md.add(new MenuItem("Eins"));
md.add(new MenuItem("-")); // Separator
md.add(new MenuItem("Zwei"));
md.add(new MenuItem("Drei"));
md.add(new MenuItem("Vier"));
mb.add(md);
}
}
fr.setMenuBar(mb);
fr.setSize(200, 100);
fr.setVisible(true);
Übung Menu
• Verändern Sie das obige Programm DemoMenu.java, so dass ein beliebiges Untermenu angezeigt wird.
• Wie gehen Sie vor, wenn Sie das gleiche Untermenu an mehreren
Stellen in Ihrem Menu einbinden müssten. Gehen Sie möglichst objektorientiert vor und programmieren Sie Ihre Lösung.
 Frank Koch
77
Textfield
TextField t = new TextField("Defaulttext");
Pop-up Menu
Choice c = new Choice();
c.addItem("Choice 1");
c.addItem("Choice 2");
c.addItem("Choice 3");
fr.add(c));
Checkbox
Checkbox cb = new Checkbox("Text");
 Frank Koch
78
Einfache Grafik und AWT
Ein einfaches Grafik-Programm unter AWT:
// GraficDemo1.java
// Einfaches Grafik-Programm
import java.awt.*;
class GraphicDemo extends Frame {
public GraphicDemo() {
setSize(400, 400);
setTitle("GraphicDemo");
}
public void paint(Graphics g) {
g.setColor(Color.red);
g.fillOval(200, 200, 50, 20);
}
public static void main(String [ ] args) {
GraphicDemo gd = new GraphicDemo();
gd.show();
}
}
 Frank Koch
79
Dynamische Grafik und AWT
Ein dynamisches Grafik-Programm unter AWT:
// GraficDemo2.java
// Dynamisches Grafik-Programm
import java.awt.*;
class Oval
{
private int m_x, m_y, m_h, m_w;
private Color m_c;
public Oval(int x,int y,int h,int w, Color c) {
m_x = x; m_y = y; m_h = h; m_w = w; m_c = c;
}
public void wachse() {
m_h++; m_w++;
}
public void paint(Graphics g) {
g.setColor(m_c);
g.fillOval(m_x, m_y, m_h, m_w);
}
}
class GraphicDemo extends Frame {
Oval m_o = new Oval(0, 0, 30, 10, Color.red);
public GraphicDemo() {
setSize(400, 400);
setTitle("GraphicDemo");
}
public void paint(Graphics g) {
m_o.paint(g);
m_o.wachse();
repaint();
}
public static void main(String [ ] args) {
GraphicDemo gd = new GraphicDemo();
gd.show();
}
}
 Frank Koch
80
Events
Events (Mausklicks, Mausbewegungen, ...) bieten den Benutzern eines GUIs die
Möglichkeit, mit der Anwendung zu interagieren. Das Java-Laufzeitsystem erkennt
solche Events und leitet sie an die den Event auslösenden Objekte weiter. In dieser
Komponente wird dann die vordefinierte Methode
public boolean handleEvent(Event ev)
aufgerufen, welche den Event analysiert (switch()) und die jeweilige ebenfalls im Objekt vordefiniert Ereignisbearbeitungsmethode aufruft. Solche Ereignisbearbeitungsmethoden sind:
boolean action(Event ev, Object obj)
boolean mouseDown(Event ev, int x, int y)
boolean mouseDrag(Event ev, int x, int y)
boolean mouseEnter(Event ev, int x, int y)
boolean mouseExit(Event ev, int x, int y)
boolean mouseUp(Event ev, int x, int y)
boolean keyDown(Event ev, int key)
Ein Kontrollelement wurde manipuliert z.B. Button
gedrückt. In obj befindet sich das korespondierende Kontrollelement.
Der Mausknopf wurde an der Position x, y gedrückt.
Die Maus wurde über ein Kontrollelement bewegt,
während ein Knopf gedrückt ist.
Der Mauszeiger tritt in den Bereich des Kontrollelements ein.
Der Mauszeiger verlässt den Bereich des Kontrollelements.
Der Mausknopf wird losgelassen.
Die Taste <key> wurde gedrückt.
Der action Event:
Der action Event für einen Button wird beim Klick auf den Button generiert; der action
Event für ein TextField wird durch die <Enter>-Taste generiert, wenn sich der Cursor
im TextField befindet. Der action Event veranlasst die objekteigene handleEvent()Methode die objekteigene action()-Methode aufzurufen. Diese Methode liefert den
Default-Wert false zurück, was bedeuted, dass der Event nicht behandelt wurde.
Dies hat zur Folge, dass der Event an das das Auslöse-Objekt einbettende Objekt
(Parent) weitergeleitet wird (Frame- oder Panel-Objekt, wenn das Button-Objekt darin eingebettet ist). Dieses Weiterreichen geschieht solange, bis die action()-Methode
den Wert true liefert.
Damit entstehen zwei Möglichkeiten auf Events zu reagieren:
1) Eine action()-Methode kann für jedes Kontrollelement überschrieben werden um
die gewünschte Funktionalität zu implementieren. Bei drei Button-Objekten könnten wir also die Klassen ButtonOne, ButtonTwo und ButtonThree aus Button ableiten. Die TwoButton.action()-Methode würde dann den action Event erhalten,
wenn Button2 geklickt wurde. Leider entstehen auf diese Weise sehr viele Klassen, was zu einer Aufblähung und Dezentralisierung des Codes führt.
2) Behandeln die Kontrollelemente den action Event nicht selbst, so wird dieser an
das Parent-Objekt weitergeleitet (Das Parent-Objekt einer Komponenten ist der
Container, dem die Komponenten hinzugefügt wurde). Überschreiben wir die action()-Methode des Parentobjekts, so erhalten wir alle action Events an einem
Ort. Nun aber müssen wir herausfinden, welches Objekt den Event ausgelöst hat.
Dazu wird der action()-Methode das Event-Objekt (hier ev) übergeben. Mit
ev.target haben wir eine Referenz zu dem auslösenden Objekt und ev.arg
beinhaltet den neuen Zustand des auslösenden Objekts (z.B. der Text innerhalb
eines TextField). Übrigens ist ev.arg identisch zu obj.
 Frank Koch
81
Events Beispiel (1/3)
Der nachfolgende Code demonstriert ein mehrschichtiges Even-Handling. Dazu gehört folgendes User Interface:
Nachfolgend die Ausgabe, wenn auf obigen User Interface die Buttons von links
oben nach recht unten geclickt werden:
Click auf
MyButtonTrueInPanel
MyButtonFalseInPanel
ButtonInPanel
ButtonInFrame(local)
ButtonInFrame(global)
Eingabe in das Textfeld
 Frank Koch
Reaktion Event Handling
MyButtonTrue->MyButtonTrueInPanel
MyButtonFalse->MyButtonFalseInPanel
MyPanel->MyButtonFalseInPanel
MyPanel->ButtonInPanel
MyFrame (instance)>ButtonInFrame(local)
MyFrame (m_b)->ButtonInFrame(global)
MyFrame (m_t)->hallo
82
Events Beispiel (2/3)
// Events1.java
// Demonstriert Events auf verschiedenen Stufen
import java.awt.*;
class MyButtonTrue extends Button
{
public MyButtonTrue(String s) {
super(s);
setBackground(Color.green);
}
public boolean action(Event ev, Object obj) {
System.out.println("MyButtonTrue->" + getLabel());
return true;
}
}
class MyButtonFalse extends Button
{
public MyButtonFalse(String s) {
super(s);
setBackground(Color.red);
}
public boolean action(Event ev, Object obj) {
System.out.println("MyButtonFalse->" + getLabel());
return false;
}
}
class MyPanel extends Panel
{
public MyPanel() {
setLayout(new FlowLayout());
setBackground(Color.blue);
add(new MyButtonTrue("MyButtonTrueInPanel"));
add(new MyButtonFalse("MyButtonFalseInPanel"));
add(new Button("ButtonInPanel"));
}
public boolean action(Event ev, Object obj) {
System.out.println("MyPanel->" +
((Button)ev.target).getLabel());
return true;
}
}
 Frank Koch
83
Events Beispiel (3/3)
class MyFrame extends Frame
{
private TextField m_t = new
TextField("TextField(global)");
private Button m_b = new Button("ButtonInFrame(global)");
}
public MyFrame(String s) {
super(s);
setLayout(new GridLayout(4,1));
add(new MyPanel());
add(new Button("ButtonInFrame(local)"));
add(m_b);
add(m_t);
pack();
setVisible(true);
}
public boolean action(Event ev, Object obj) {
if (ev.target == m_b) { // Button global
String str = ((Button)ev.target).getLabel();
System.out.println("MyFrame (m_b)->" + str);
return true;
}
else if (ev.target instanceof Button) {
String str = ((Button)ev.target).getLabel();
System.out.println("MyFrame(instance)->" + str);
return true;
}
// Das folgende else ist eine schlechte Alternative
else if (ev.target == m_t) { // TextField global
String str = ((TextField)ev.target).getText();
System.out.println("MyFrame (m_t)->" + str);
return true;
}
return false;
}
public static void main(String[] args) {
new MyFrame("EventDemo");
}
 Frank Koch
84
Interne Klassen / Nested Classes
Windows-Events werden mit dem WindowsListener behandelt.
import java.awt.*;
import java.awt.event.*; // Für addWindowListener
class MyFrame extends Frame
{
public MyFrame(String title) {
super(title); // Aufruf geerbter Konstruktor
// Instanziierung & Definition einer Internen Klasse
WindowAdapter wa = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
// Reaktion auf Windows-Events
addWindowListener(wa);
}
}
... wie gehabt ...
public boolean action(Event ev, Object obj) {
... wie gehabt ...
}
class EventDemo
{
... wie gehabt ...
}
 Frank Koch
85
Übung Calendar
Im Unterricht wird Ihnen der Bytecode zu dem Programm Calendar zur Verfügung gestellt, der folgenden Output erzeugt:
"Spielen" Sie mit der Benutzerschnittstelle dieser Applikation,
um daraus Rückschlüsse auf das Event-Modell zu gewinnen.
Programmieren Sie anschliessend Ihren eigenen Calendar.
Mein Calendar ist noch recht einfach. Natürlich könnte man
die Anzahl Tage-Buttons abhängig vom ausgewählten Monat/Jahr anzeigen. Auch könnte man die Tage-Buttons nicht
horizontal sondern vertikal durchlaufen lassen und nach Wochen gruppieren. Machen Sie mehr aus Ihrem Calendar...
Die Lösung finden Sie im Anhang.
 Frank Koch
86
Anhang: Lösung Calendar (1/2)
// Calendar einfach Version
import java.awt.*;
class Days extends Panel
{
public Days() {
setLayout(new GridLayout(7, 5));
for(int i=1; i<=31; i++)
add(new Button("" + i));
}
}
class Calendar extends Frame
{
private TextField m_textField = new TextField("");
private Choice m_months = new Choice();
private Choice m_years = new Choice();
private int m_d, m_m, m_y;
public Calendar(String s) {
super(s);
m_d = 1; m_m = 1; m_y = 2002;
m_textField.setText(m_d + "." + m_m + "." + m_y);
}
setLayout(new BorderLayout());
// Choice Box Monate
m_months.addItem("Januar");
m_months.addItem("Februar");
m_months.addItem("März");
m_months.addItem("April");
m_months.addItem("Mai");
m_months.addItem("Juni");
m_months.addItem("Juli");
m_months.addItem("August");
m_months.addItem("September");
m_months.addItem("Oktober");
m_months.addItem("November");
m_months.addItem("Dezember");
m_months.select(m_m-1);
// Choice Box Jahre
for(int i=1990; i<2020; i++)
m_years.addItem(""+i);
m_years.select("" + m_y);
// Zusammensetzen Kontrollelemente
Panel p = new Panel();
p.add(m_months);
p.add(m_years);
add("North", p);
add("Center", new DayPanel(31));
add("South", m_textField);
pack();
setVisible(true);
public void updateTextField(String dmy, int value) {
if (dmy.equals("Day"))
m_d = value;
if (dmy.equals("Month")) m_m = value;
if (dmy.equals("Year")) m_y = value;
m_textField.setText(m_d + "." + m_m + "." + m_y);
}
 Frank Koch
87
public boolean action(Event ev, Object obj) {
// War es ein Button?
if (ev.target instanceof Button) {
String str = ((Button)ev.target).getLabel();
// Welcher Button war es?
for(int i=1; i<=31; i++)
if (str.equals("" + i))
updateTextField("Day", i);
return true;
}
// War es die Monats Choice?
if (ev.target == m_months) {
String str = m_months.getSelectedItem();
if (str.equals("Januar"))
updateTextField("Month", 1);
if (str.equals("Februar"))
updateTextField("Month", 2);
if (str.equals("März"))
updateTextField("Month", 3);
if (str.equals("April"))
updateTextField("Month", 4);
if (str.equals("Mai"))
updateTextField("Month", 5);
if (str.equals("Juni"))
updateTextField("Month", 6);
if (str.equals("Juli"))
updateTextField("Month", 7);
if (str.equals("August"))
updateTextField("Month", 8);
if (str.equals("September"))
updateTextField("Month", 9);
if (str.equals("Oktober"))
updateTextField("Month", 10);
if (str.equals("November"))
updateTextField("Month", 11);
if (str.equals("Dezember"))
updateTextField("Month", 12);
return true;
}
// War es die Jahres Choice?
if (ev.target == m_years) {
updateTextField("Year", Integer.parseInt(m_years.getSelectedItem()));
return true;
}
return false;
}
}
public static void main(String[] args) {
new Calendar("MyCalendar");
}
 Frank Koch
88
Übung Ball
Im Verzeichnis ..\Java\Src\Awt\Ball (Bestandteil von Java_src.exe) finden Sie einige Java Programme aus dem Buch
„Object Oriented Programming with Java“ von Timothy Budd.
Studieren Sie den Code dieser Programme und erarbeiten Sie
ein Verständnis der Programmstruktur sowie der Klassendefinitionen.
Programm
Beschreibung
Source
Ball World
Ein Frame mit einem rollenden Ball
BallWorld.java
Ein Frame mit
mehreren rollenden Bällen
MultiBallWorld.java
Interaktives Kanonenfeuern
CannonWorld.java
Multi Ball World
Cannon World
Ball.java
Ball.java
Ball.java
(Sorry an die Pazifisten)
 Frank Koch
89
Applet Kontrollmethoden
Methode
Nutzung
public void init();
Wird beim Laden des Applets aufgerufen.
In init() sollten alle für die Arbeit des
Applets wichtigen Ressourcen (Speicherplätze, Initialisierungen, ...) bereitgestellt
werden.
public void start();
Diese Methode wird unmittelbar nach init()
aufgerufen und enthält den eigentlichen
Applet-Code. start() wird auch aufgerufen,
wenn das Applet neu dargestellt werden
muss (Klick auf Aktualisieren, oder Wechsel auf eine andere WebPage mit anschliessender Rückkehr)
public void stop();
Diese Methode ist das Gegenstück von
start() und wird aufgerufen, wenn die
WebPage verlassen oder der Browser beendet wird.
public void destroy(); Diese Methode ist das Gegenstück von
init() und wird aufgerufen, wenn der Browser beendet wird.
public void
paint(Graphics g);
Diese Methode wird immer dann aufgerufen, wenn das Applet wiederhergestellt
werden muss (z.B. weil es verdeckt wurde).
Szenario:
1) Wir laden das Applet in den Browser: init(), start(), paint()
2) Wir browsen zu einer anderen WebPage: stop()
3) Wir gehen zurück auf die vorige WebPage: start(), paint()
4) Wir browsen zu einer anderen WebPage: stop()
5) Wir gehen zurück auf die vorige WebPage: start(), paint()
6) Wir verdecken das Browserfenster und holen es wieder
hervor: paint()
7) Wir beenden den Browser: destroy()
 Frank Koch
90
Beispiel Methods
import java.applet.Applet;
import java.awt.Graphics;
public class Methods extends Applet {
private int m_paint;
private int m_init;
private int m_start;
private int m_stop;
private int m_destroy;
public Methods() {
m_paint = 0;
m_init = 0;
m_start = 0;
m_stop = 0;
m_destroy = 0;
}
public void init() {
resize(320, 240);
m_init++;
}
public void start() {
m_start++;
}
public void stop() {
m_stop++;
}
public void destroy() {
m_destroy++;
}
public void paint(Graphics g) {
m_paint++;
g.drawString("paint
= " +
g.drawString("init
= " +
g.drawString("start
= " +
g.drawString("stop
= " +
g.drawString("destroy = " +
}
}
m_paint, 0, 10);
m_init, 0, 20);
m_start, 0, 30);
m_stop, 0, 40);
m_destroy, 0, 50);
Output obiges Szenario:
Dieser Output zeigt paint mit 5 anstatt
wie erwartet mit 4 an. Grund ist der
weitere Aufruf der paint()-Methode
beim Einfangen des Windows.
 Frank Koch
91
Applet Events
Applets reagieren nicht nur auf die Aufrufe des Browsers. Auch Benutzer-Interaktionen (Mausklick, Mausbewegung, Tastatureingabe) können
mit Events behandelt werden.
Wie schon im Kapitel "The Java Event Model" gezeigt, verfügen auch
Applets über einen Event-Handler (handleEvent()-Methode aus der
Klasse Component), die mit jedem Event aufgerufen wird und die dem
Event zugeordnete Ereignisbehandlungsmethode aufruft. Diese Ereignisbehandlungsmethoden sind:
Der Mauscursor tritt in den AppletBereich ein.
Der Mauscursor tritt aus dem AppletBereich aus.
Wird mit jeder Mausbewegung aufgerufen, wenn kein Mausknopf gedrückt
wurde.
boolean mouseDrag(Event evt, Wird mit jeder Mausbewegung aufgerufen, wenn der Mausknopf gedrückt
int x, int y)
wurde.
Der Mausknopf wurde gedrückt.
boolean mouseDown(Event
evt, int x, int y)
Der Mausknopf wird losgelassen.
boolean mouseUp(Event evt,
int x, int y)
boolean keyDown(Event evt, int Eine Taste wurde gedrückt während
das Applet-Window aktiv war.
key)
Eine Taste wurde losgelasssen wähboolean keyUp(Event evt, int
rend das Applet-Window aktiv war.
key)
Das Applet-Window wird auf aktiv geboolean gotFocus(Event evt,
setzt.
Object what)
Boolean lostFocus(Event evt, Das Applet-Window wird auf inaktiv
gesetzt.
Object what)
boolean mouseEnter(Event evt,
int x, int y)
boolean mouseExit(Event evt,
int x, int y)
boolean mouseMove(Event evt,
int x, int y)
 Frank Koch
92
Events Beispiel
import java.applet.*;
import java.awt.*;
public class Events extends Applet {
private Dimension m_cursorLoc; // location of cursor
private boolean m_drag; // True if we're dragging
public void init() {
resize(640, 480);
}
public void paint(Graphics g) {
String cursorLoc = "(" + m_cursorLoc.width + "," +
m_cursorLoc.height + ")";
g.drawString(cursorLoc, 10, 20);
if (m_drag)
g.setColor(Color.red);
else
g.setColor(Color.black);
int x = m_cursorLoc.width;
int y = m_cursorLoc.height;
g.drawLine(x-4, y, x+4, y);
g.drawLine(x, y-4, x, y+4);
}
public boolean mouseDrag(Event evt, int x, int y) {
m_drag = true;
m_cursorLoc = new Dimension(x, y);
repaint(); // forces a repaint of the window
return true;
}
public boolean mouseMove(Event evt, int x, int y) {
m_drag = false;
m_cursorLoc = new Dimension(x, y);
repaint(); // forces a repaint of the window
return true;
}
}
 Frank Koch
93
Übung Connector
Erweitern Sie das soeben besprochenen Applet (Nennen Sie es nun
"Connector"). Mit jedem mouseDown-Event speichern Sie die jeweilige Cursorposition (Array) und
zeichnen eine Linie zwischen dieser Position und allen anderen bislang angeklickten Positionen. Weiterhin sind die Cursorbewegungen
mit dem bekannten Kreuz darzustellen.
Die Lösung finden Sie im Anhang.
Erweiterung der Übung: Das oben vorgeschlagene Array hat die Einschränkung, dass zur
Programmierzeit entschieden wird, wieviele Positionen gespeichert werden können. Das folgende Beispiel zur Klasse
Vector (dynamisch veränderbares Array) soll Ihnen eine Idee
geben, wie Sie Ihre Lösung dynamisch anlegen können.
Schauen Sie auch mal in die Hilfe.
import java.util.*;
public class VectorTest {
public static void main (String args[]) {
Vector v = new Vector(10);
myClass mc = new myClass();
mc.setName("Heidi");
v.addElement(mc);
// Cast, da Vector generisch ist
System.out.println(((myClass)v.elementAt(0)).getName());
}
}
 Frank Koch
94
Anhang: Lösung Connector
import java.applet.*;
import java.awt.*;
class Connector extends Applet {
static final int m_MAXLOCS = 100;
private Dimension m_locs[]; // records clicked locations
private int m_noClicks; // number of mouse clicks
private Dimension m_cursorLoc; // location of cursor
public Connector() {
m_locs = new Dimension[m_MAXLOCS];
m_noClicks = 0;
}
public void init() {
resize(640, 480);
}
public void paint(Graphics g) {
// connect all memorized locations with each other
for(int i=0; i<m_noClicks-1; i++) {
for(int j=i+1; j<m_noClicks; j++) {
g.drawLine(m_locs[i].width,
m_locs[i].height,
m_locs[j].width,
m_locs[j].height);
}
}
}
public boolean mouseDown(Event evt, int x, int y) {
if (m_noClicks < m_MAXLOCS) {
m_locs[m_noClicks] = new Dimension(x, y);
m_noClicks++;
repaint();
}
return true;
}
}
 Frank Koch
95
Applets und Threads
public class AppThread extends Applet implements Runnable
{
Thread thread = null;
public void start() {
thread = new Thread(this);
thread.start();
}
public void run() {
while(thread != null) {
...
}
}
public void stop() {
thread.stop();
thread = null;
}
 Frank Koch
96
Übung Nochmal Ball
Haben Sie im AWT-Teil die Java Programme aus dem Verzeichnis ..\Java\Src\Awt\Ball (Bestandteil von Java_src.exe)
studiert? Dann können wir die Übung nun für Applets erweitern:
Ändern Sie das Multi Ball World-Programm so, dass es als
Applet läuft. Testen Sie es mit dem Appletviewer aus dem
JDK.
Für Fortgeschrittene und Begeisterte:
Ändern Sie das Cannon World-Programm so, dass es als
Applet läuft.
 Frank Koch
97
I/O-Klassen
Object
interface DataInput
interface DataOutput
InputStream
FileInputStream
PipedInputStream
ByteArrayInputStream
StringBufferInputStream
SequenceInputStream
FilterInputStream
BufferedInputStream
DataInputStream
LineNumberInputStream
PushBackInputStream
StreamTokenizer
OutputStream
FileOutputStream
PipedOutputStream
ByteArrayOutputStream
FilterOutputStream
BufferedOutputStream
DataOutputStream
PrintStream
RandomAccessFile
File
interface FileNameFilter
FileDescriptor
Throwable
Exception
IOException
EOFException
FileNotFoundException
InterruptedIOException
UTFDataFormatException
 Frank Koch
98
System.in und System.out
import java.io.*;
class ConsolIO
{
public static void main(String[] args) {
byte bArray[] = new byte[20];
System.out.println("Eingabe:");
try {
System.in.read(bArray);
}
catch(IOException ioe) { // für read
System.out.println(ioe.toString());
ioe.printStackTrace();
}
System.out.print("Sie gaben ein: ");
// Die Zeile 'System.out.println(bArray);'
// läge nahe, aber System.out (PrintStream)
// kann kein Bytearray ausgeben
String s = new String(bArray, 0);
System.out.println(s);
}
}
 Frank Koch
99
Simple File I/O
import java.io.*;
public class FileCopy {
public static void main(String[] args) {
File inputFile = new File("in.txt");
File outputFile = new File("out.txt");
try {
FileReader in = new FileReader(inputFile);
FileWriter out = new FileWriter(outputFile);
int c;
while ((c = in.read()) != -1)
out.write(c);
in.close();
out.close();
}
catch (Exception e) {e.getMessage();}
}
}
 Frank Koch
100
Buffered File I/O
import java.io.*;
class BufferedFileCopy
{
public static void main(String[] args) {
try {
byte bArray[] = new byte[128];
int no;
FileInputStream in =
new FileInputStream("in.txt");
// add buffering to that Input Stream
BufferedInputStream bin =
new BufferedInputStream(in);
FileOutputStream out =
new FileOutputStream("out.txt");
// add buffering to that Input Stream
BufferedOutputStream bout =
new BufferedOutputStream(out);
while(bin.available() > 0) {
// read in 128 bytes
no = bin.read(bArray);
// write out read bytes
bout.write(bArray, 0, no);
}
bout.flush();
}
catch(IOException ioe) {
System.out.println(ioe.toString());
}
}
}
 Frank Koch
101
URL Application
import java.net.*;
import java.io.*;
public class UrlApplication
{
public static void main(String[] args)
{
try {
URL theURL = new
URL("http://home.zhwin.ch/~kfr/Java/URLTest/UrlText.txt");
InputStream in = theURL.openStream();
DataInputStream data = new
DataInputStream(in);
String line;
while((line = data.readLine()) != null) {
System.out.println(line);
}
}
catch(IOException e) {System.out.println(e);}
}
}
 Frank Koch
102
URL Applet (1/3)
1. Das angestrebte Resultat (Web-Server-File wird in Applet angezeigt)
2. Einloggen über den FTP-Client auf den Web-Server
3. Aufladen der Files über den FTP-Client auf den Web-Server
 Frank Koch
103
URL Applet (2/3)
import
import
import
import
import
import
import
java.awt.*;
java.io.DataInputStream;
java.io.BufferedInputStream;
java.io.IOException;
java.net.URL;
java.net.URLConnection;
java.net.MalformedURLException;
public class UrlApplet extends java.applet.Applet implements
Runnable {
Thread runner;
URL theURL;
TextArea ta = new TextArea("Getting my text ...");
public void init() {
setLayout(new GridLayout(1, 1));
String url =
"http://home.zhwin.ch/~kfr/Java/URLTest/UrlText.txt";
try {this.theURL = new URL(url);}
catch(MalformedURLException e) {System.out.println("Bad URL: " + theURL);}
add(ta);
}
public Insets insets() {
return new Insets(10, 10, 10, 10);
}
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
 Frank Koch
104
public void run() {
URLConnection conn = null;
DataInputStream data = null;
String line;
StringBuffer buf = new StringBuffer();
try {
conn = this.theURL.openConnection();
conn.connect();
ta.setText("Connection opened ...");
data = new DataInputStream(conn.getInputStream());
ta.setText("Reading data ...");
while ((line = data.readLine()) != null) {
buf.append(line + "\n");
}
ta.setText(buf.toString());
}
catch (IOException e) {
System.out.println("IO Error:" +
e.getMessage());
}
}
}
 Frank Koch
105
Client/Server mit Sockets
Server
Client
Socket
Socket
Bind
Listen
Accept(s)
Connection establishment
In/Out
Close
 Frank Koch
Netzwerk
Connect
In/Out
Close
106
Client/Server mit Sockets
Initialisierung Server:
Für die Implementation eines Server stellt Java die Klasse ServerSocket zur Verfügung. Durch eine Instanzierung eines solchen Sockets werden bereits die Methoden
Socket.open(), bind() und listen() ausgeführt.
ServerSocket listenSocket = new ServerSocket(PortID);
Accept, In/Out sowie das Schliessen eines Socket müssen vom Programmierer ausgelöst werden.
Socket clientSocket = listenSocket.accept();
....
listenSocket.close();
Initialisierung Client:
Der Client benutzt die Klasse Socket. Sie vereinigt die Aktionen Socket.open() und
connect() bei der Instanzierung.
Socket s = new Socket(Hostname, RemotePort);
Der eigene Port des Clients wir per default immer dynamisch von der Runtime vergeben. Geschlossen wird dieses Socket wie beim Server mit:
s.close();
Kommunikation:
Die Kommunikation der beiden Prozesse erfolgt in der Aktion In/Out. Diese müssen
bei der Initialisierung der Verbindung zuerst erstellt werden.
Client :
DataInputStream in = new DataInputStream(s.getInputStream());
PrintStream out = new PrintStream(s.getOutputStream());
Server :
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
PrintStream out = new PrintStream(clientSocket.getOutputStream());
Beispiel:
Nachstehend die Ausgabe des Client/Server Pgms auf den nächsten Seiten. Der
Client liest von der Standardeingabe ganze Zeilen ein und übermittelt sie dem Server. Der Server dreht jeden erhaltenen String um und schickt ihn an den Client zurück. Die gedrehten Zeilen werden danach vom Client wieder ausgegeben.
> java Server
Server: listening on port 8001
Press enter to stop the server
> java Client 127.0.0.1 8001
Connected to localhost/127.0.0.1 : 8001
> Hallo
ollaH
>
 Frank Koch
107
Client/Server Beispiel (Server (1/2))
import java.io.*;
import java.net.*;
public class Server extends Thread {
public final static int DEFAULT_PORT = 8001;
protected
int port;
protected ServerSocket listen_socket;
// Exit with an error message, when an exception occurs.
public static void fail(Exception e, String msg) {
System.err.println(msg + ": " + e);
System.exit(1);
}
// Create a ServerSocket to listen for connections on;
public Server(int port) {
start the thread.
if (port == 0) port = DEFAULT_PORT;
this.port = port;
try { listen_socket = new ServerSocket(port); }
catch (IOException e) { fail(e, "Exception creating server socket"); }
}
System.out.println("Server: listening on port " + port);
this.start();
public void run() {
try {
}
while(true) {
// save the copy of the new created socket
Socket client_socket = listen_socket.accept();
// Start workerthread
Connection c = new Connection(client_socket);
}
}
catch (IOException e) { fail(e, "Exception while listening"); }
// Start the server up, listening on an optionally specified port
public static void main(String[] args) {
int port = 0;
if (args.length == 1) {
try { port = Integer.parseInt(args[0]); }
catch (NumberFormatException e) { port = 0; }
}
// Start a server by creating its instance
Server s = new Server(port);
}
}
 Frank Koch
System.out.println("Press enter to stop the server");
try {
int i = System.in.read();
}
catch ( IOException e) {
System.err.println(e);
}
System.out.println("Client Shutdown");
s.stop();
System.exit(0);
108
Client/Server Beispiel (Server (2/2))
// This class is
class Connection
protected
protected
protected
the thread that handles all communication with a client
extends Thread {
Socket
client;
DataInputStream in;
PrintStream
out;
// Initialize the streams and start the thread
public Connection(Socket client_socket) {
}
client = client_socket;
try {
in = new DataInputStream(client.getInputStream());
out = new PrintStream(client.getOutputStream());
}
catch (IOException e) {
try { client.close(); }
catch (IOException e2) {};
System.err.println("Exception while getting socket streams: " + e);
return;
}
this.start();
// Provide the service.
// Read a line, reverse it, send it back.
public void run() {
String line;
StringBuffer revline;
int len;
try {
while(true) {
// read in a line
line = in.readLine();
if (line.compareTo("") == 0) {
System.out.println("Client Shutdown");
break;
}
len = line.length();
revline = new StringBuffer(len);
for(int i = len-1; i >= 0; i--)
revline.insert(len-1-i, line.charAt(i));
// and write out the reversed line
out.println(revline);
}
}
catch (IOException e) {
System.err.println(e);
}
finally {
try {
}
}
 Frank Koch
}
client.close();
}
catch (IOException e2) {};
109
Client/Server Beispiel (Client)
import java.io.*;
import java.net.*;
public class Client {
// see ports under c:\windows\service
public static final int DEFAULT_PORT = 8001;
public static void usage() {
System.out.println("Usage: java Client <hostname> [<port>]");
System.exit(0);
}
public static void main(String[] args) {
int
port = DEFAULT_PORT;
Socket
s = null;
String line;
if ((args.length != 1) && (args.length != 2)) Client.usage();
if (args.length == 1) port = DEFAULT_PORT;
else {
try { port = Integer.parseInt(args[1]); }
catch (NumberFormatException e) { usage(); }
}
try {
s = new Socket(args[0], port); // hostname:port
DataInputStream sin = new DataInputStream(s.getInputStream());
PrintStream
sout = new PrintStream(s.getOutputStream());
// Create a stream for reading lines of text from the console
DataInputStream
in = new DataInputStream(System.in);
System.out.println("Connected to " + s.getInetAddress()
+ " : "+ s.getPort());
while(true) {
System.out.print("> ");
System.out.flush();
}
}
}
}
 Frank Koch
// print a prompt
// read a line from the console, empty line means exit
line = in.readLine();
if ( line.compareTo("")==0 ) {
System.out.println("Client Shutdown");
sout.println(line);
break;
}
sout.println(line);
line = sin.readLine();
if (line == null) {
System.out.println("Connection closed by server.");
break;
}
System.out.println(line);
catch (IOException e) {
System.err.println(e);
}
// Always be sure to close the socket
finally {
try { if (s != null) s.close(); }
catch (IOException e2) {};
}
110
Übung POP3-MailClient
Nutzen wir das erarbeitete Wissen um einen POP3-MailClient zu erstellen. Der POP3-Server befindet sich gewöhnlich auf dem Port 110. Nachstehend finden Sie die POP3-Befehle, die Sie vom Client an den POP3MailServer senden können.
user <pop user>
pass <password>
quit
list
top <msg no> <n>
dele <msg no>
retr <msg no>
Für das Connect zum Server: z.B. user kfr.
Für das Connect zum Server: z.B. pass geheimnis.
Beenden der Verbindung zum Server.
Listet wartende Mails mit Nummer und Grösse.
Ausgabe des Headers sowie der ersten n Zeilen
eines Mails. Das Ende der Ausgabe wird mit einem
Punkt auf einer separaten Zeile indiziert.
Löschen eines Mails (Das Mail wird nur markiert
und erst nach "quit" wirklich gelöscht).
Runterladen des kompletten Mails.
Schreiben Sie einen MailClient, mit dem Sie Ihre Mails auf dem MailServer ansehen können.
 Frank Koch
111
SMTP und FTP Services
Zur Komplettierung finden Sie nachstehend die Befehlstabellen zu weiteren Services.
SMTP (Wellknown Port 25)
HELO <client name>
Anforderung einer Verbindung; Authentifizierung ist nicht notwendig.
MAIL FROM:<mail address> Absenderdaten
RCPT TO:<mail address>
Empfängerdaten
DATA
Nachrichtentext (Darin muss der eigentliche Header mit allen Angaben über
Subject usw. angegeben werden). Abschluss durch: Leerzeile Punkt Leerzeile.
QUIT
Beenden der Verbindung.
FTP (Wellknown Port 21)
USER <user name>
PASS <password>
CWD <directory>
RETR <filename>
QUIT
 Frank Koch
Für das Connect zum Server.
Für das Connect zum Server.
Verzeichnis auf dem Server wechseln
Datei holen
Beenden der Verbindung zum Server.
112
JDBC – Lokaler DB-Zugriff
Mit JDBC hat Sun einen Standard definiert, um aus Java-Programmen
heraus auf relationale Datenbanken zugreifen zu können. Das Akronym
steht für Java Database Connectivity und stellt ein API mit einer Reihe
von Klassen, Interfaces und Methoden zur Verfügung, deren sich der
Programmierer bedienen kann. Zwei Besonderheiten zeichnen JDBC
aus:
• Der Datenbankzugriff erfolgt unabhängig von verwendeten Datenbanksystem.
• Alle DBMS-spezifischen Details übernimmt ein JDBC-Treiber. Er ist in
Java geschrieben und wird von den DB-Herstellern angeboten.
Mittels einer JDBC-ODBC-Bridge kann via JDBC auch auf jede ODBCDB zugegriffen werden. Mehr Informationen hierzu finden Sie in dem
ausgeteilten Kapitel 2 „JDBC in der Praxis“.
Installationsanleitung:
1) Speichern Sie kfr.mdb auf Ihrem lokalen Rechner
2) Registrieren Sie kfr.mdb in ODBC unter dem Namen javatesterlocal.
Unter NT und XP öffnen Sie hierzu die Systemsteuerung/Verwaltung und
klicken doppelt auf as Icon "ODBC", unter Umständen mit dem Zusatz
"32". Im erscheinenden Fenster wählen Sie die Registrierkarte "System",
klicken auf "Hinzufügen", "MS Access Treiber". Unter "Datenquellennamen" geben Sie den Namen an, unter dem die Datenbank später von
Java aus zugreifbar ist. Wir wollen Sie hier "javatesterlocal" nennen. Klicken Sie nun auf "Auswählen" und suchen Sie die frisch abgespeicherte
Datenbank "kfr.mdb". Klicken Sie auf OK und die Datenbank ist registriert.
3) Modifizieren Sie ..\Src\Jdbc\Adressen.java für den lokalen Zugriff (siehe im Code)
 Frank Koch
113
JDBC - Elementare JDBC Befehle
import java.sql.*;
// Laden des Treibers JDBC-ODBC-Bridge
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// Connect to DB
// ODBC Registrierung "javatesterlocal"
String url = "jdbc:odbc:javatesterlocal ";
Connection connection =
DriverManager.getConnection(url,"admin","");
// Aufbereitung und Ausführung einer SQL-Anweisung
Statement s = connection.createStatement();
Resultset r =
s.executeQuery("SELECT * FROM Adressen");
// Abfragen von DB-Metadaten
DatabaseMetaData meta = connection.getMetaData();
System.out.println(meta.getDriverName());
System.out.println(meta.getDriverVersion ());
System.out.println(meta.getURL ());
// Lesen der Zeilen bis EOF
while(r.next()) {
// Erstes Feld
System.out.println(r.getString(1));
// Zweites Feld
System.out.println(r.getString(2));
...
}
// Schliessen des Zugriffs
r.close();
s.close();
connection.close();
 Frank Koch
114
JDBC – Remote DB-Zugriff
Mit der JDBC-ODBC-Bridge kann auch auf Datenbanken zugegriffen
werden, die sich im Netzwerk oder Internet befinden. Für diese Übung
steht uns auf dem Linux Server 160.85.169.102 die MySQL Datenbank
„javatester“ zur Verfügung. Wir können auf diese Datenbank unter der
UserID „student“ sowie dem Passwort „student“ zugreifen. Die Datenbank beinhaltet u.a. den Table „Adressen“. Weitere Angaben finden Sie
in der Datei ..\Src\JDBC\installation.txt.
Zwei Szenarien sind möglich:
ODBC-Treiber befindet sich auf dem Abfrage-Client:
• Der ODBC-Treiber
http://www.mysql.com/Downloads/MyODBC/myodbc-2.50.39-nt.zip ist
auf der lokalen Maschine zu installieren. Sie finden diesen Treiber
auch unter Src\Downloads\Tools.
• Registrieren Sie die MySQL-DB in dem neuen ODBC-Treiber unter
dem Namen „wf_javadsn“. Die Zugangsdaten für den ODBC-Eintrag
in unserem Beispiel sind:
o Windows DSN Name: wf_java
o MySQL host: 160.85.169.102
o MySQL database name: javatester
o User: student
o PW: student
o Port: 3306
• Modifizieren Sie Adressen.java für den Remote Zugriff (siehe Kommentare im Code).
• Alternativ können Sie die MySQL-DB auch mit dem MySQL-FrontEnd
http://www.mysql.com/Downloads/ MySQL-Front_2.2_Setup.exe ansehen. Sie finden dieses Programm auch unter Src\Downloads\Tools.
• Alternativ können Sie die MySQL-DB auch über Access einsehen, indem sie dort die ODBC-Quelle „javatesterremote“ zugreifen.
ODBC-Treiber befindet sich auf dem DB-Server:
• Auf dem Linux-Server ist bereits ein ODBC-Treiber installiert.
• JDataConnect_2201.zip ist auf der lokalen Maschine zu installieren.
Sie finden diesen Treiber auch unter Src\Downloads\Tools.
• Zugriffe erfolgen direkt aus Java.
 Frank Koch
115
Übung JDBC und AWT
Erstellen Sie ein Java-Pgm, dass mittels eines GUI die folgenden Operationen für unsere kfr-DB erlaubt:
• Abfragen vorhandener Sätze
• Einfügen neuer Sätze
• Ändern bzw. Mutieren bestehender Sätze
• Löschen bestehender Sätze
 Frank Koch
116
CGI (1/7)
Greift man mit einem Browser auf einen Web-Server zu, so haben wir es
mit einer Web-spezifischen Form der Client/Server-Programmierung zutun. Wir wollen nun den Fall betrachten, wenn dem Benutzer am HTMLClient Daten bereitgestellt werden sollen, die sich in einer DB auf der
Server-Seite befinden. Wir benutzen nochmals unsere DB kfr.mdb aus
den Schritten 2 und 3 zuvor. Den restlichen Code finden Sie auch unter
..\Src\CGI.
Schritt 1: Wir erstellen die HTML-Abfragemaske CGITest.html für den
Client. In diesem Bsp soll nach einem PLZ-Bereich gesucht werden können.
<HTML>
<HEAD>
<TITLE>Adress-Suche</TITLE>
</HEAD>
<BODY>
<H1>Adresssuche</H1>
<P>
Bitte den Postleitzahlenbereich der gew&uuml;nschten
Adressen eingeben!
</P>
<FORM METHOD="POST" ACTION="/kfr/CGITest/CGITest.bat">
<P>
Von <INPUT TYPE="text" NAME="VON" VALUE="00000" SIZE=5>
bis <INPUT TYPE="text" NAME="BIS" VALUE="99999" SIZE=5>
</P>
<P>
<INPUT TYPE="submit" VALUE="Abschicken!">
</P>
</FORM>
</BODY>
</HTML>
Mit der Zeile <FORM METHOD="POST" ACTION="/kfr/CGITest/CGITest.bat"> werden die URL des Clients sowie alle Daten, die der Benutzer in das Formular eingegeben hat ("Query-String") an den Web-Server übermittelt.
Zur Verarbeitung dieser Daten startet der Web-Server dann in einem eigenen Prozess das CGI-Skript „CGITest.bat“, dem er die URL und den
Query-String über die Standardeingabe (stdin) zur Verfügung stellt. Dieses CGI-Skript läuft auf der Server-Maschine und befindet sich bei uns
im Verzeichnis CGITest.
 Frank Koch
117
CGI (2/7)
Schritt 2: Nun erstellen wir das CGI-Script. Damit das CGI-Skript weiss,
wieviele Daten es über die Standardeingabe (stdin) einlesen soll, wird
ihm die Anzahl Bytes durch den Web-Server über die Umgebebungsvariable CONTENT_LENGTH mitgeteilt. Ein solches CGI-Skript kann in einer Vielzahl Sprachen formuliert werden, z.B. UNIX-Skript, DOS-Batch,
PERL, C, Visual Basic und natürlich Java. Java hat den Vorteil, dass es
portabel ist; kann aber gerade deshalb nicht auf die Umgebebungsvariable CONTENT_LENGTH zugreifen. Wir brauchen daher neben dem
Java-Pgm (hier CGITest.java) ein kleines Wrapper-Skript (hier CGITest.bat),
@echo off
java Adressen "%CONTENT_LENGTH%"
dass die Umgebungsvariable ausliest und dem Java-Pgm als Parameter
liefert. Weiterhin startet das Wrapper-Skript den Java-Interpreter, der die
Klasse CGITest.class startet. Das Java-Pgm liest nun den Query-String
über stdin ein und erhält daraus die vom Benutzer eingegebenen Parameter. In diesem Beispiel werden die Parameter als Suchkriterien für einen JDBC-Zugriff benutzt. Das Java-Pgm generiert nun eine Ausgabe im
HTML-Format auf die Standardausgabe (stdout). Der wartende WebServer nimmt diese Ausgabe als HTML-Seite an und sendet diese an
den wartenden Client retoure.
Anmerkung: Das Beispiel wurde so vorbereitet, dass es sowohl mit als
auch ohne Web-Server lauffähig ist. Das abgedruckte Skript enthält beide Varianten, wobei die „mit-Server“-Variante auskommentiert ist.
 Frank Koch
118
CGI (3/7)
import java.sql.*;
import java.io.*;
//
//
//
//
Standard CGI-Skript, liest einen Parameter (die Länge
des Parameterstrings) sowie den Parameterstring über
Stdin und gibt dieses aus. Weiterhin werden die
Systemvariablen von Java ausgegeben.
public class Adressen {
static String query_string;
// HTML-Kopf ausgeben
static void htmlhead() {
System.out.println("Content-type: text/html");
System.out.println("");
System.out.println("<HTML>");
System.out.println("<HEAD>");
System.out.println("<TITLE>CGI-Test</TITLE>");
System.out.println("</HEAD>");
System.out.println("<BODY>");
}
// HTML-Seite abschließen
static void htmlfoot() {
System.out.println("</BODY>");
System.out.println("</HTML>");
}
// Parameter aus CGI-String auslesen
static String getParameter(String name) {
String backstring;
// Extrahiert aus der globalen Variable query_string
// den Eintrag "name" und gibt den Inhalt zurück.
// "=" an name hängen
name = name + "=";
int i;
for (i = 0;
(i < query_string.length() - name.length())
&& !(name.equalsIgnoreCase(
query_string.substring(i, name.length() +
i))); i++);
 Frank Koch
119
CGI (4/7)
// Ist Name gefunden worden?
if (i < query_string.length() - name.length()) {
// Ja -> in "backstring" ablegen
backstring = query_string.substring
(i + name.length ());
if (backstring.indexOf("&") >= 0)
backstring = backstring.substring
(0, backstring.indexOf("&"));
} else {
// Nein, leeren String ablegen
backstring = "";
}
// Nun noch falsche Zeichen ersetzen
// erst alle "+" in Leerzeichen
backstring = backstring.replace('+', ' ');
// Nun Unicode-Zeichen
i = 0;
while (i < backstring.length ()) {
if (backstring.charAt (i) == '%')
backstring = backstring.substring(0, i) +
(char)Integer.parseInt
(backstring.substring(i+1, i+3), 16) +
i++;
}
backstring.substring(i+3);
}
return backstring;
static void cgi_prog() {
// Kopf ausgeben
htmlhead ();
String von = getParameter("VON");
String bis = getParameter("BIS");
// Überschrift ausgeben
System.out.println("<H1>Die Resultate der Anfrage "
+ von + " .. " + bis + " :</H1>");
// zunächst muß der JdbcOdbc-Treiber geladen werden
try {
Class.forName ("sun.jdbc.odbc.JdbcOdbcDriver");
}
catch(Exception e) {
System.out.println("<P>Datenbanktreiber nicht
gefunden!</P>");
return;
}
 Frank Koch
120
CGI (5/7)
// OK, Treiber geladen, nun eine Verbindung herstellen
try {
Connection verbindung = DriverManager.getConnection("jdbc:odbc:kfrdsn", "admin", "");
// Metadaten beziehen und ausgeben, falls vorhanden
DatabaseMetaData metadaten = verbindung.getMetaData();
if (metadaten == null) {
System.out.println("<P>Keine Metadaten
verfügbar</P>");
} else {
System.out.println("<P>Die befragte Datenbank ist " + metadaten.getDatabaseProductName() + "</P>");
System.out.println("<P>Versionsnummer: "
+ metadaten.getDatabaseProductVersion() + "</P>");
}
// Eine Abfrage (query) erstellen
Statement query = verbindung.createStatement();
// ... und formulieren...
ResultSet ergebnisse =
query.executeQuery("SELECT * FROM Adressen WHERE ((PLZ >= " +
von.trim() + ") and (PLZ <= "+bis.trim()+ ")) order by
name");
// herausfinden, welche Felder welche Tabellenpositionen besitzen
int pos_name = ergebnisse.findColumn("Name");
int pos_vorname = ergebnisse.findColumn("Vorname");
int pos_strasse = ergebnisse.findColumn("Strasse");
int pos_plz = ergebnisse.findColumn("PLZ");
int pos_ort = ergebnisse.findColumn("Ort");
int pos_telefon = ergebnisse.findColumn("Telefon");
int pos_fax = ergebnisse.findColumn("Fax");
 Frank Koch
121
CGI (6/7)
// Und alle Ergebnisse auslesen, in einer Tabelle anzeigen...
System.out.println("<TABLE BORDER>");
System.out.println("<TR>");
System.out.println("<TH>Name</TH>");
System.out.println("<TH>Vorname</TH>");
System.out.println("<TH>Stra&szlig;e</TH>");
System.out.println("<TH>PLZ</TH>");
System.out.println("<TH>Ort</TH>");
System.out.println("<TH>Telefon</TH>");
System.out.println("<TH>Fax</TH>");
System.out.println("</TR>");
while(ergebnisse.next()) {
System.out.println ("<TR>");
System.out.println("<TD>"+
ergebnisse.getString(pos_name)+"</TD>");
System.out.println("<TD>"+
ergebnisse.getString(pos_vorname)+"</TD>");
System.out.println("<TD>"+
ergebnisse.getString(pos_strasse)+"</TD>");
System.out.println("<TD>"+
ergebnisse.getString(pos_plz)+"</TD>");
System.out.println("<TD>"+
ergebnisse.getString(pos_ort)+"</TD>");
System.out.println("<TD>"+
ergebnisse.getString(pos_telefon)+"</TD>");
System.out.println("<TD>"+
ergebnisse.getString(pos_fax)+"</TD>");
System.out.println ("</TR>");
}
// und Tabelle schließen
System.out.println("</TABLE>");
// Verbindung auflösen
verbindung.close ();
}
catch(Exception e) {
// Es ist irgendein Datenbankfehler aufgetreten: genaue Meldung ausgeben
System.out.println("<P>Datenbankfehler:</P>");
System.out.println("<PRE>");
System.out.println(e.getMessage ());
e.printStackTrace(System.out);
System.out.println("</PRE>");
}
// Fuß ausgeben
htmlfoot ();
}
 Frank Koch
122
CGI (7/7)
public static void main (String args[]) {
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! CODE FÜR VORHANDENEN WEB-SERVER
// !!! // Die Länge der übermittelten Daten aus dem
// !!! // ersten Parameter auslesen und in die
// !!! // Variable content_length schreiben.
// !!! int content_length = Integer.parseInt(args[0]);
// !!! // einen entsprechend großen Pufferspeicher
// !!! // instanziieren
// !!! byte buffer[] = new byte[content_length + 1];
//
//
//
//
//
!!!
!!!
!!!
!!!
!!!
//
//
//
//
//
//
!!! }
!!! catch(IOException e) {
!!!
System.out.println("Lesefehler");
!!! };
!!! query_string = new String(buffer);
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!
versuchen, die Daten einzulesen (kann nur
// bei einem Fehler des Servers oder bei
// falscher Übertragungsmethode (GET)
// schiefgehen.
try {
System.in.read(buffer, 0, content_length);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! CODE FÜR SIMULIERTEN WEB-SERVER
query_string = args[1];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
cgi_prog();
Anmerkung: Das Beispiel wurde so vorbereitet, dass es sowohl mit als
auch ohne Web-Server lauffähig ist. Das abgedruckte Pgm enthält beide
Varianten, wobei die „mit-Server“-Variante auskommentiert ist.
 Frank Koch
123
Servlets
Hier: Servlet generiert komplette HTML-Page als Output.
Web-Browser
1
7
Web-Server
2
6
Servlet-Engine
3
5
Servlet-Klasse
4a
Netzwerk
4b
FileSystem
Legende:
1) Browser: http-Request aus Browser (z.B.
http://ServerName/servlets/FirstServlet).
2) Web-Server: Anhand „fehlender“ Extension wird Servlet erkannt und der Request an die Servlet-Engine weitergegeben.
3) Servlet-Eingine: Ruft die Servlet-Klasse auf
4) Servlet-Klasse kann nun auf die Hostressourcen (z.B.: Netzwerk, File-System)
zugreifen.
5) Die Servlet-Klasse generiert HTML-Output und gibt diesen an Servlet-Eingine
zurück.
6) HTML wird an Web-Server weitergereicht.
7) HTML wird an Web-Browser weitergereicht.
 Frank Koch
124
Servlets
Hier: Servlet generiert einen Teil der HTML-Page als Output.
Web-Browser
1
9
Web-Server
2
Servlet-Engine
4
3
7
8
JSSI
6
Servlet-Klasse
5a
Netzwerk
5b
FileSystem
Legende:
1) Browser: http-Request aus Browser (z.B.
http://ServerName/servlets/FirstJSSI.jhtml).
2) Web-Server: Anhand .jhtml Extension wird Servlet erkannt und der Request an
den JSSI-Parser weitergegeben.
3) JSSI parst die Servlet-Befehle heraus und gibt diese an die Servlet-Engine weiter.
4) Servlet-Eingine: Ruft die Servlet-Klasse auf
5) Servlet-Klasse kann nun auf die Hostressourcen (z.B.: Netzwerk, File-System)
zugreifen.
6) Die Servlet-Klasse generiert HTML-Output und gibt diesen an Servlet-Eingine
zurück.
7) HTML wird an JSSI weitergereicht.
8) JSSI ersetzt die Servlet-Befehle gegen das generierte HTML und gibt ein
HTML-File an den Web-Server zurück.
9) HTML wird an den Web-Browser weitergereicht.
 Frank Koch
125
Servlets (Installation)
ACHTUNG: Nehmen Sie diese Installation NICHT in der Schule vor !!!
Nachstehend die Reihenfolge sowie Kommentare zur Installation:
•
HTTP-Server: z.B.: Apache 1.1.9 oder höher (hier 1.3.11) (apache_1_3_11_win32.exe)
•
Installieren
•
C:\Programe\Apache Group\Apache\conf\httpd.conf editieren. Evtl ‚#‘ vor
„servername“ entfernen (Eintrag unter servername spielt hier keine Rolle).
•
Test: Apache starten und im Browser den Rechnernamen bzw die IPNummer eingeben. Bei Erfolg erscheint Apache-Startseite im Browser.
•
JDK1.2 (falls noch nicht installiert): (jdk1_2_2-001-win.exe und jdk1_2_2-001doc.zip)
•
Java Servlet Development Kit 2.0 (jsdk20-win32.exe). Klassenpakete für das
Kompilieren der Servlets.
•
•
Installieren
•
Web-Server runterfahren und neu starten.
Apache Servlet Engine: Vor installieren von ApacheJServ unbedingt JSDK2.0
installieren. ApacheJServ am Besten mit jdk1.1.8 verwenden. Es gibt Probleme
mit der CLASSPATH Variablen im jdk1.2 (ApacheJServ-1_1.exe)
•
•
•
Installieren (Pfadnamen müssen eingegeben werden)
•
Java Virtual Machine: c:\jdk1.2.2\bin
•
JSDK: c:\jsdk2.0
Bestätigen, dass Installationsskript das Apache-Konfigurationsfile aktualisieren soll.
Apache JSSI Parser: (ApacheJSSI-1_1_2.zip)
 Frank Koch
126
Servlets (FirstServlet)
KofFirstServlet.java
import
import
import
import
import
java.io.PrintWriter;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
public class KofFirstServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>FirstServlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<H1>FirstServlet</H1>");
out.println("</BODY>");
out.println("</HTML>");
out.close();
}
}
//
//
//
//
//
//
//
Nachfolgend für JSSI-Beispiel
response.setContentType("text/html");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
PrintWriter out = response.getWriter();
out.println("<H1>Hello World</H1>");
out.close();
•
Speicherort: c:\Programme\Apache Jserv 1.1\servlets\FirstServlet.class
•
Aufruf über: http://ServerName/servlets/KofFirstServlet (Der WebServer erkennt
anhand der fehlenden Extension, dass der Aufruf an die Servlet-Engine weitergeleitet werden muss.
•
Der vom Servlet generierte HTML-Output wird an den wartenden WebServer
zurückgegeben.
 Frank Koch
127
Servlets (FileReadServlet)
KofFileReadServlet.java
import
import
import
import
import
import
import
import
import
java.io.IOException;
java.io.BufferedReader;
java.io.FileReader;
java.io.IOException;
java.io.PrintWriter;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
public class KofFileReadServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>FileReadServlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
readFile(out);
out.println("</BODY>");
out.println("</HTML>");
}
private void readFile(PrintWriter out)
throws IOException {
String file=
("c:/programme/apache jserv 1.1/servlets/text.txt")
}
}
BufferedReader reader = new BufferedReader(
new FileReader(file));
String line = reader.readLine();
while(line != null) {
out.println(line);
out.println("<BR>");
line = reader.readLine();
}
•
Speicherort: c:\Programme\Apache Jserv 1.1\servlets\FileReadServlet.class
•
Aufruf über: http://ServerName/servlets/KofFileReadServlet
 Frank Koch
128
Servlets (DBReadServlet)
KofDBReadServlet.java
import
import
import
import
import
import
import
import
import
import
java.io.IOException;
java.io.PrintWriter;
java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.Statement;
javax.servlet.ServletException;
// Kawa Classpath siehe unten
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
public class KofDBReadServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>KofDataBaseReadServlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
readFromDataBase(out);
out.println("</BODY>");
out.println("</HTML>");
}
private void readFromDataBase(PrintWriter out) throws IOException {
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:kfrdsn";
Connection c = DriverManager.getConnection(url, "", "");
Statement s = c.createStatement();
out.println("<TABLE BORDER=\"1\">");
out.println("<TR>");
out.println("<TD>Vorname</TD>");
out.println("<TD>Nachname</TD>");
out.println("<TD>email</TD>");
out.println("</TR>");
ResultSet rs = s.executeQuery("select * from Emails");
while(rs.next()) {
out.println("<TR>");
out.println("<TD>" + rs.getString("vorname") + "</TD>");
out.println("<TD>" + rs.getString("nachname") + "</TD>");
out.println("<TD>" + rs.getString("email") + "</TD>");
}
}
out.println("</TR>");
}
out.println("</TABLE>");
rs.close();
s.close();
c.close();
} catch(Exception ex) {}
•
Kawa: Menü
•
Speicherort: c:\Programme\Apache Jserv 1.1\servlets\DBReadServlet.class
•
Aufruf über: http://ServerName/servlets/KofDBReadServlet
 Frank Koch
Packages
Classpath Eintrag: C:\JSDK2.0\lib\jsdk.jar
129
Servlets (Email-Suche)
EmailSuche.html
<HTML>
<HEAD>
<TITLE>Email-Suche</TITLE>
</HEAD>
<BODY>
<H1>Email Suche</H1>
Bitte geben Sie Vor- und/oder Nachname bzw. Teile davon ein.<BR>
<FORM ACTION="servlets/KofEmailFromDataBaseServlet" METHOD="GET">
Vorname:<BR>
<INPUT TYPE="TEXT" SIZE="20" NAME="Vorname"><BR>
Nachname:<BR>
<INPUT TYPE="TEXT" SIZE="20" NAME="Nachname"><BR>
<INPUT TYPE="SUBMIT" VALUE="Suche starten" NAME="b">
</FORM>
</BODY>
</HTML>
KofEmailFromDataBaseServlet.java
import
import
import
import
import
import
import
import
import
import
java.io.IOException;
java.io.PrintWriter;
java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.Statement;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
public class KofEmailFromDataBaseServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Suchergebnis</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
readFromDataBase(request, out);
out.println("</BODY>");
out.println("</HTML>");
}
private void readFromDataBase(HttpServletRequest request, PrintWriter out) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:kfrdsn";
connection = DriverManager.getConnection(url, "", "");
statement = connection.createStatement();
out.println("<TABLE BORDER=\"1\">");
out.println("<TR>");
out.println("<TD>Vorname</TD>");
out.println("<TD>Nachname</TD>");
out.println("<TD>email</TD>");
out.println("</TR>");
ResultSet rs = statement.executeQuery(getSQLRequest(request));
while(rs.next()) {
out.println("<TR>");
out.println("<TD>" + rs.getString("vorname") + "</TD>");
out.println("<TD>" + rs.getString("nachname") + "</TD>");
out.println("<TD>" + rs.getString("email") + "</TD>");
out.println("</TR>");
}
 Frank Koch
130
out.println("</TABLE>");
rs.close();
statement.close();
connection.close();
} catch(Exception ex) {
} finally {
try {
statement.close();
} catch(Exception cEx1){}
try {
connection.close();
} catch(Exception cEx2){}
}
}
private String getSQLRequest(HttpServletRequest request) {
String firstName = request.getParameter("Vorname");
String lastName = request.getParameter("Nachname");
if(((firstName == null) && (lastName == null)) ||
((firstName.length() == 0) && (lastName.length() == 0))) {
return "";
}
if((firstName != null) && (firstName.length() > 0)) {
if((lastName != null) && (lastName.length() > 0)) {
return searchForFirstAndLastName(firstName, lastName);
} else {
return searchForFirstName(firstName);
}
} else {
return searchForLastName(lastName);
}
}
private String searchForFirstAndLastName(String firstName,
String lastName) {
return "select vorname, nachname, email from EmailTs " +
"where vorname like '%" + firstName +
"%' AND nachname like '%" + lastName + "%'";
}
private String searchForFirstName(String firstName) {
return "select vorname, nachname, email from Emails " +
"where vorname like '%" + firstName + "%'";
}
}
private String searchForLastName(String lastName) {
return "select vorname, nachname, email from Emails " +
"where nachname like '%" + lastName + "%'";
}
•
Kawa: Menü
•
Speicherort: c:\Programme\Apache Jserv 1.1\servlets\KofEmailFromDataBaseServlet.class
•
Speicherort: c:\WebServerRoot\KofEmailSuche.html
•
Aufruf über: http://ServerName/servlets/KofEmailSuche.html
 Frank Koch
Packages
Classpath Eintrag: C:\JSDK2.0\lib\jsdk.jar
131
Servlets (Debugging von Servlets)
KofDebugEmailFromDataBaseServlet.java
import
import
import
import
import
import
import
import
import
import
import
java.io.IOException;
java.io.PrintWriter;
java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.Statement;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
tools.servlet.ServletTools;
// Für Ausgabe auf JavaConsole
public class KofDebugEmailFromDataBaseServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
ServletTools.init();
// Für Ausgabe auf JavaConsole
try {
PrintWriter out = response.getWriter();
out.println("<HEAD>");
out.println("<TITLE>Suchergebnis</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
readFromDataBase(request, out);
out.println("</BODY>");
out.println("</HTML>");
String test = null;
test.toUpperCase(); // Hier provozieren wir eine Excpetion
}
catch(Throwable t) {t.printStackTrace();} // Für Ausgabe auf Console
}
....
}
•
Kawa: Menü
Packages
Classpath Eintrag: C:\Programme\Apache
JServ 1.1\servlets\Htmltool.jar
•
Speicherort: c:\Programme\Apache Jserv 1.1\servlets\DebugEmailFromDataBaseServlet.class
•
Speicherort: c:\WebServerRoot\servlets/KofDebugEmailSuche.html
•
Aufruf über: http://ServerName/servlets/KofDebugEmailSuche.html
 Frank Koch
132
JavaScript (1.1) - Positionierung
HTML-Dokumente sind passiv; Interaktion mit dem Benutzer ist nur eingeschränkt
möglich. Oft aber sollte der Inhalt des angezeigten Dokuments auf Benutzerreaktinen angepasst werden. Aus diesem Grunde entwickelte Netscape "ActiveScript",
das im Dezember 1995 in Zusammenarbeit mit Sun an deren Sprache Java angepasst und in "JavaScript" umgetauft wurde.
Java ist ein offener Standard, der von namhaften Softwarehäusern unterstützt wird
und zum "de facto-Standard" für interaktive WebPages wurde.
JavaScript und HTML
JavaScript ermöglicht es Aktionen und Eingaben von Benutzern zu verarbeiten. Es
erlaubt die Steuerung des Kontrollflusses, wodurch es möglich wird Algorithmen zu
implementieren und die Bearbeitung von HTML-Anweisungen gezielt zu steuern.
JavaScript und Java
Gemeinsamkeiten:
• JavaScript hat Syntax und Sprachelemente weitgehend von Java übernommen.
• Java ist eine Allzweck-Pgmiersprache, die sich besonders gut für das Internet
eignet. JavaScript wurde speziell für den Einsatz in WWW-Dokumenten entworfen. JavsScript bildet somit eine Teilmenge des Einsatzbereiches von Java.
Unterschiede:
• Objektorientiert (Java) versus objektbasiert (JavaScript). JavaScript ist eine
prozedurale Sprache, die zusätzlich über ein stark eingeschränktes Objektkonzept verfügt und sich auf bestimmte, vordefinierte Objekte beschränkt (keine
Vererbung, kein Polymorphismus).
• Starke (Java) versus schwache (JavaScript) Typisierung
• Komplex (Java) versus einfach (JavaScript)
• Kompiliert (Java) versus interpretiert (JavaScript)
• Bytecode (Java) versus Einbindung in HTML (JavaScript)
Vorzüge von JavaScript
• Leicht erlernbar
• Kurze Entwicklungszeit
• Kompakte Sprache
• Plattformunabhängig
Nachteile von JavaScript
• Beschränktes EInsatzgebiet
• Nicht für komplexe Anwendungen geeignet
• Nicht für zeitkritische Anwendungen geeignet
• Skripte sind Bestandteil der HTML-Pages und für jedermann einsehbar
Anmerkung
Um JavaScript zu verstehen, hilft es ein wenig über HTML zu wissen. Schauen Sie
sich dazu doch einmal die Kursunterlage von Hubert Partl an.
 Frank Koch
133
JavaScript – Beispiel „BenutzerIO“
<HTML>
<HEAD>
<META NAME="Author" CONTENT="Frank Koch">
<TITLE>JavaScript BenutzerIO</TITLE>
</HEAD>
<BODY>
<CENTER>
<B><FONT SIZE=+4>
Guten Tag!<BR>
<SCRIPT LANGUAGE="JavaScript">
name = prompt("Wie heissen Sie?", "");
document.write("Hallo " + name + ",<BR>");
document.write("hat mich gefreut, ");
document.write("Sie kennenzulernen.<BR>");
</SCRIPT>
Auf Wiedersehen!
</FONT></B>
</CENTER>
</BODY>
</HTML>
 Frank Koch
134
JavaScript – Bsp „Diskontierung“ (1/3)
 Frank Koch
135
JavaScript – Bsp „Diskontierung“ (2/3)
<HTML>
<HEAD>
<META NAME="Author" CONTENT="Frank Koch">
<TITLE>JavaScript Diskontierung</TITLE>
</HEAD>
<BODY>
<CENTER>
<B><FONT SIZE=+4>
<SCRIPT LANGUAGE="JavaScript">
// Funktionsdefinitionen
function berechneZinsen(betrag, zinssatz) {
return(betrag * (zinssatz / 100.0));
}
function berechneRealenWert(betrag, inflationsrate) {
return(betrag / (1.0 + (inflationsrate / 100.0)));
}
function runden(wert) {
return(Math.round(wert * 100.0) / 100.0);
}
// Eingabevariablen
var anfangskapital, zinssatz, inflationsrate, anlagezeitraum;
// Variablen zur Kennzeichnung korrekter Eingaben
var anfangskapitalOK, zinssatzOK, inflationsrateOK, anlagezeitraumOK;
// Variablen für die zu berechnenden Werte
var kapital, zinsen, realesKapital, realeZinsen;
// Eingabe des Anfangskapitals
while(!anfangskapitalOK) {
anfangskapital = prompt("Geben Sie das Anfangskapital ein", "0");
anfangskapital = parseFloat(anfangskapital);
if ((!isNaN(anfangskapital)) && (anfangskapital >= 0.0)) {
anfangskapitalOK = true;
} else {
alert("Geben Sie ein Zahl grösser oder gleich Null ein");
}
}
// Eingabe des Zinssatzes
while(!zinssatzOK) {
zinssatz = prompt("Geben Sie den Zinssatz in % ein", "0");
zinssatz = parseFloat(zinssatz);
if ((!isNaN(zinssatz)) && (zinssatz >= 0.0)) {
zinssatzOK = true;
} else {
alert("Geben Sie ein Zahl grösser oder gleich Null ein");
}
}
 Frank Koch
136
JavaScript – Bsp „Diskontierung“ (3/3)
// Eingabe der Inflationsrate
while(!inflationsrateOK) {
inflationsrate = prompt("Geben Sie die Inflationsrate in % ein",
"0");
inflationsrate = parseFloat(inflationsrate);
if (!isNaN(inflationsrate)) {
inflationsrateOK = true;
} else {
alert("Geben Sie ein Zahl ein");
}
}
// Eingabe des Anlagezeitraumes
while(!anlagezeitraumOK) {
anlagezeitraum = prompt("Geben Sie den Anlagezeitraum in Jahren
(1..100) ein", "0");
anlagezeitraum = parseFloat(anlagezeitraum);
if ((!isNaN(anlagezeitraum)) && (anlagezeitraum >= 1) && (anlagezeitraum <= 100)) {
anlagezeitraumOK = true;
} else {
alert("Geben Sie ein Zahl zwischen 1 und 100 ein");
}
}
// Werte ausgeben
document.write("Anfangskapital: ", runden(anfangskapital), " CHF<BR>");
document.write("Zinssatz: ", runden(zinssatz), " %<BR>");
document.write("Inflationsrate: ", runden(inflationsrate), " %<BR>");
document.writeln("Anlagezeitraum: ", runden(anlagezeitraum), " Jahre<BR>");
// Tabellenkopf
document.writeln("<TABLE BORDER>");
document.write("<CAPTION>Wertentwicklung unter Berücksichtigung von");
document.writeln("Verzinsung und Inflation</CAPTION>");
document.write("<TR><TH>Jahre</TH>");
document.write("<TH>Zinsen</TH>");
document.write("<TH>Guthaben</TH>");
document.write("<TH>Tatsächliche Zinsen</TH>");
document.write("<TH>Tatsächliches Guthaben</TH></TR>");
// Werte in der Tabelle
realesKapital = kapital = anfangskapital;
for(var jahre = 1; jahre <= anlagezeitraum; jahre++) {
document.write("<TR><TD>");
document.write(jahre, "</TD><TD>");
zinsen = berechneZinsen(kapital, zinssatz);
document.write(runden(zinsen), "</TD><TD>");
kapital += zinsen;
document.write(runden(kapital), "</TD><TD>");
realeZinsen = berechneRealenWert(zinsen, inflationsrate);
document.write(runden(realeZinsen), "</TD><TD>");
realesKapital += zinsen;
realesKapital = berechneRealenWert(realesKapital, inflationsrate);
document.writeln(runden(realesKapital), "</TD></TR>");
}
document.writeln("</TABLE>");
</SCRIPT>
</FONT></B>
</CENTER>
</BODY>
 Frank Koch
137
</HTML>
 Frank Koch
138
JavaScript – Bedeutung für Java
Java ist eine Allzweck-Programmiersprache. Alles, was in
HTML oder JavaScript möglich ist, könnte man auch in Java
realisieren. In der Praxis greift man trotzdem gerne auf HTML
und JavaScript zurück, weil sie die Aufgaben, für die sie entwickelt wurden, einfach und schnell lösen können. Beispielsweise kann man mit Java Dialogboxen und Formulare erstellen; der dafür benötigte Aufwand ist jedoch weit grösser als in
HTML und JavaScript.
Ideal ist es, wenn man diese verschiedenen Entwicklungswerkzeuge je nach deren Stärken einsetzen könnte. Voraussetzung dafür ist, dass sich HTML, JavaScript und Java nahtlos miteinander verbinden lassen.
Der "Kitt" zwischen HTML und Java ist JavaScript. In HTMLScript gibt es das applet-Objekt, über das es möglich ist, öffentliche Variablen und Methoden eines durch den applet-Tag
eingebundenen Java-Applets anzusprechen. Variablen können sowohl gelesen als auch verändert werden. Die Eigenschaften und Methoden des jeweiligen applet-Objekts hängen
dabei von zugehörigen Java-Applet ab.
 Frank Koch
139
JavaScript – Bsp „AppletLink“
Applet-Teil
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Font;
public class AppletLink extends Applet {
Font m_f;
int m_size = 12;
String m_text = "leer";
public void newText(String text) {
m_text = text;
repaint();
}
public void addSize() {
m_size++;
m_f = new Font("Arial", 2, m_size);
repaint();
}
public void init() {
m_f = new Font("Arial", 2, m_size);
}
public void paint(Graphics g) {
g.setFont(m_f);
g.drawString("Text="+m_text+" Grösse="+m_size,10,50);
}
}
HTML-Teil
<HTML>
<HEAD>
<META NAME="Author" CONTENT="Frank Koch">
<TITLE>JavaScript AppletLink</TITLE>
</HEAD>
<BODY>
<CENTER>
<B><FONT SIZE=+4>
<APPLET CODE="AppletLink.class" NAME="applet" WIDTH=300 HEIGHT=100>
</APPLET>
<SCRIPT LANGUAGE="JavaScript">
</SCRIPT>
<FORM>
<INPUT TYPE="TEXT" NAME="text" VALUE="mein Text"
ONCHANGE="applet.newText(value)">
<INPUT TYPE="BUTTON" NAME="button" VALUE="Grösser"
ONCLICK="applet.addSize()">
</FORM>
</FONT></B>
</CENTER>
</BODY>
</HTML>
 Frank Koch
140
javadoc
•
•
•
javadoc parses the declarations and documentation comments in a set of Java
source files and produces a set of HTML pages describing, by default, the public
and protected classes, interfaces, constructors, methods, and fields. As an argument to javadoc you pass in either a series of Java package names or source
files.
javadoc generates one .html file for each .java file and each packages it encounters. In addition, it produces a class hierarchy (tree.html) and an index of those
members (AllNames.html).
When javadoc parses the class and member delarations, it picks up their signatures for inclusion. In addition, you can add further documentation by including
doc comments (masked by /** and */) in the source code.
Beispiel: „javadoc.java“ mit javadoc-Comments:
/**
* My comment for class 'Super':
* <pre>
*
Super s = new Super();
*
s.methodeSuper();
* </pre>
*/
public class Super {
public void methodeSuper() {}
}
/**
* My comment for class 'Sub':
* <pre>
*
Sub s = new Sub();
*
s.publicMethode();
* </pre>
*/
public class Sub extends Super {
/**
* My comment for variable 'publicVariable':
*/
public int publicVariable;
/**
* My comment for variable 'privateVariable':
*/
private int privateVariable;
/**
* My comment for methode 'publicMethode':
* @param void
* @return void
* @exception no exception
*/
public void publicMethode() {}
private void privateMethode() {}
}
Erzeugung der Dokumentation:
javadoc javadoc.java
 Frank Koch
141
Reflexion bzw Introspection
// Gibt die Methoden einer zuvor unbekannten Klasse
//(hier: Random) aus
import java.lang.reflect.*;
import java.util.Random;
class Reflexion {
public static void main(String[] arguments) {
Random rd = new Random(); // Random wird gewählt
Class className = rd.getClass();
Method[] methods = className.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println("Method: " + methods[i]);
}
}
}
Ausgabe:
Method: public final native java.lang.Class java.lang.Object.getClass()
Method: public native int java.lang.Object.hashCode()
Method: public boolean java.lang.Object.equals(java.lang.Object)
Method: public java.lang.String java.lang.Object.toString()
Method: public final native void java.lang.Object.notify()
Method: public final native void java.lang.Object.notifyAll()
Method: public final native void java.lang.Object.wait(long) throws
java.lang.InterruptedException
Method: public final void java.lang.Object.wait(long,int) throws
java.lang.InterruptedException
Method: public final void java.lang.Object.wait() throws
java.lang.InterruptedException
Method: public synchronized void java.util.Random.setSeed(long)
Method: public void java.util.Random.nextBytes(byte[])
Method: public int java.util.Random.nextInt()
Method: public long java.util.Random.nextLong()
Method: public float java.util.Random.nextFloat()
Method: public double java.util.Random.nextDouble()
Method: public synchronized double java.util.Random.nextGaussian()
 Frank Koch
142
Locale
import java.util.Locale;
class TestLocale {
public static void main(String[] arguments) {
Locale l = new Locale("DE", "CH");
System.out.println(l.getCountry());
System.out.println(l.getLanguage());
System.out.println(l.toString());
System.out.println(l.getDisplayLanguage());
System.out.println(l.getDisplayCountry());
System.out.println(l.getDisplayName());
}
}
Ausgabe:
CH
De
De_CH
Deutsch
Schweiz
Deutsch (Schweiz)
 Frank Koch
143
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement