Einleitung
Sprachkonstrukte
Applets
Servlets und JSP
Zusammenfassung und Ausblick
Programmiersprache der Firma SUN
vollständige objektorientierte Programmiersprache
Interpreter
Unterschiede zu anderen OO-Sprachen
Sicherheit
Java als "Web-Programmiersprache"
Java ist eine Programmiersprache mit den folgenden Merkmalen: einfach, objekt-orientiert, verteilt, interpretiert, sicher, architektur-neutral, portabel, multithreaded und dynamisch. Sie ist für parallele und verteilte Programmierung besonders geeignet, vor allem wegen der in die Sprache integrierten Thread- und Synchronisationskonstrukte, Sicherheitsmaßnahmen, dynamisch ladbaren Klassen und der seit Java 1.1 und Java 1.2 vorhandenen Techniken Remote Method Invocation (RMI) und Object Serialization.
Das einfachste, immer wieder eingesetzte Programm druckt nur Hello World! und terminiert dann.
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } }
Ein solches Java-Programm wird in einen sogenannten Byte-Code kompiliert und dann mit Hilfe eines Java-Interpreters ausgeführt. Vor der Kompilation müssen jedoch einige Umgebungsvariablen gesetzt werden. Dies sind die Variablen CLASSPATH und PATH, die unter Unix/Linux in den Shells sh oder bash, wie folgt gesetzt werden.
% set CLASSPATH="/usr/local/jdk/java/lib:." % set PATH="$PATH:/usr/local/jdk/java/bin" % export CLASSPATH PATHDiese Zeilen können eingetippt oder in der Datei .bashrc dauerhaft eingetragen werden. Auf Windows-NT-Rechnern müssen diese Variablen im Systempanel entsprechend gesetzt werden. Dabei ist das Trennzeichen `:' durch `;' und das Pfadtrennzeichen `/' durch `
\
'
zu ersetzen.
In anderen Umgebungen müssen Sie die Umgebungsvariablen
entsprechend anpassen, falls sie nicht schon durch die
Installationsroutinen richtig eingestellt werden.
Die Kompilierung mit dem Byte-Code Compiler erfolgt durch javac.
% javac HelloWorld.java
Die Ausführung erfolgt mit dem Interpreter java.
% java HelloWorld
Das Ergebnis ist wie erwartet.
Hello World!
Java-Programme werden mittels Klassen definiert. Jede öffentliche (d.h. als public deklarierte) Klasse muß in einer separaten Datei gespeichert werden. Der Name der Datei muß mit dem Namen der public-Klasse übereinstimmen (z.B. muß die Klasse public class Test in der Datei Test.java gespeichert werden).
Ein Objekt einer Klasse, d.h. eine Instanz der Klasse, kann nur durch das Schlüsselwort new erzeugt werden.
Date d = new Date();
Der Speicherbereich für das Objekt wird automatisch allokiert. Wenn das Objekt nicht mehr gebraucht wird (d.h. keine Variable referenziert mehr das Objekt), wird der Speicherbereich während eines Garbage-Collection-Vorganges wieder freigegeben (Speicherrecycling). Das heißt, daß im Gegensatz zu C/C++ kein expliziter `delete'-Operator benötigt wird.
Ein Package (Paket) enthält eine oder mehrere Klassen, die sich einen Geltungsbereich (Namespace) für Klassen teilen. Klassennamen brauchen nur innerhalb eines Packages eindeutig zu sein. Dies vermeidet mögliche Namenskonflikte zwischen verschiedenen Klassen, die von der lokalen Festplatte oder über das Netz dynamisch geladen werden.
Das Java-API (Application Programming Interface) besteht aus den Klassen, die in den folgenden acht Packages definiert sind:
java.applet java.awt java.awt.image java.awt.peer java.io java.lang java.net java.utilBei dem Java-1.1-API haben sich die genannten Packages leicht geändert und es sind die folgenden Packages hinzu gekommen:
java.beans java.event java.math java.rmi java.sql java.text java.util.zipBei dem Java-1.2-API kommen neben vielen Erweiterungen und Verbesserungen vorhandener Pakete, unter anderem folgende Pakete hinzu:
java.security java.awt.swing java.awt.accessability java.lang.ref java.lang.reflect java.util.jar javax.servlet
Um eine Java-Datei einem Paket zuzuordnen, kann man an den Anfang der Datei eine package-Anweisung schreiben.
package game;Dies definiert das Package game, das die in der Datei definierten Klassen enthält. Falls die Datei keine package-Anweisung enthält, werden die in der Datei definierten Klassen dem standardmäßigen namenlosen Package zugeordnet.
Wenn man in einer Datei Klassen eines anderen Packages benutzen will, muß man den Klassennamen komplett mit Package-Namen angeben. Will man z.B. die Klasse Date im java.util-Package benutzen, so wird dies wie im unten angeführten Beispiel getan.
java.util.Date d = new java.util.Date(); System.out.println("today is: "+d);
Die vollen Packagenamen können weggelassen werden, wenn die import-Anweisung benutzt wird.
import java.util.Date; ... Date d = new Date(); System.out.println("today is: "+d);
Man kann auch mit * alle Klassennamen eines Packages oder alle Methoden und Variablen einer Klasse importieren.
import java.util.*; ... Date d = new Date(); System.out.println("today is: "+d); ... Vector v = new Vector(); v.addElement("hello"); v.addElement("bye");
Das Package java.lang enthält die Basisklassen für Java und wird immer importiert. Deswegen kann man z.B. Object, System, Integer usw. ohne ihren Package-Namen java.lang benutzen.
Eine als public deklarierte Klasse ist in allen Packages zugreifbar. Auf eine nicht als public deklarierte Klasse kann nur innerhalb desselben Package zugegriffen werden.
Zur Verdeutlichung der Konzepte betrachten wir folgende Beispiele:
public class A { public int pb; protected int pt; private int pv; /*default*/ int df; } public class B extends A { A a = new A(); /* 1 */ } public class C { A a = new A(); /* 2 */ }
An der Stelle /* 1 */ gilt folgendes:
Auf public-Felder (Variablen oder Methoden) kann in allen Packages und Subklassen zugegriffen werden, solange die Klasse selbst zugreifbar ist. Auf protected-Felder kann in Subklassen der Klasse und in allen Klassen im gleichen Package zugegriffen werden. private-Felder sind dagegen nur in derselben Klasse zugreifbar. Diese Beziehungen sind nochmal in Abbildung 1.2 zusammengefaßt.
In Java sind die primitiven Datentypen architektur-unabhängig
definiert. Eine Zusammenstellung befindet sich in
Abbildung 1.3. Der Begriff `atomar' wird
bei Mulit-threaded Programmen benötigt.
Datentyp | Inhalt | Größe | atomar |
---|---|---|---|
boolean | true oder false | 1 bit | ja |
char | Unicode Zeichen | 16 bits | ja |
byte | signed integer | 8 bits | ja |
short | signed integer | 16 bits | ja |
int | signed integer | 32 bits | ja |
long | signed integer | 64 bits | nein |
float | IEEE754 float | 32 bits | ja |
double | IEEE754 double | 64 bits | nein |
Variablen und Methoden können in einer Klasse definiert werden. Ein Objekt, das von dieser Klasse instanziiert (erzeugt) wird, enthält diese Variablen und Methoden. Statische Variablen und Methoden sind dagegen mit einer Klasse direkt verbunden.
public class Card { int number; static int base = 5; public static String version = "1.0"; public Card(int n) { number = n; } public int getNumber() { return number; } public static int getBase() { return base; } public int getDiff() { return number - base; } public static void main(String[] args) { Card c = new Card(7); System.out.println(c.version+":"+ c.getNumber()+"-"+c.getDiff()+"="+ Card.getBase()); } }Die Ausgabe dieses Programms ist 1.0:7-2=5.
Ein Array, d.h. einen Vektor oder eine Matrix, kann man ebenfalls durch new erzeugen.
byte buffer[] = new byte[4096]; byte[] data = new byte[4096]; int plot[][] = new int[64][64]; ... Date ds[] = new Date[16];
Auf die Elemente eines Arrays kann über ihren Index zugegriffen werden.
for (int i=0; i < buffer.length; i++) buffer[i] = data[i];In der length Variablen eines Array Objekts steht die Information über die Länge bereit.
Java hat die üblichen auch von C und C++ bekannten while-, do- und for-Schleifen-Konstrukte.
while (condition) { statements } do { statements } while (condition); for (int i=0; i < end; i++) { statements }break und continue können analog zu C/C++ in einer Schleife benutzt werden.
Konstante Variablen können mit dem Schlüsselwort final deklariert werden. Diese können dann nicht mehr geändert werden.
public final static String DEFAULT = "dpunkt";Im Gegensatz zu C oder C++ gibt es keinen Preprozessor, der Konstanten substituieren kann (z.B. kein #define).
Eine Exception (Ausnahmefehler) ist ein Signal, das irgendeinen Fehler andeutet. Man kann eine Exception durch throw auslösen und durch catch abfangen. Ein neues Exception-Objekt wird wie üblich mit new erzeugt. Falls eine Exception nicht in der Methode abgefangen wird, wird sie in die Methode weitergeleitet, die diese Methode aufgerufen hat. Dies ermöglicht bessere und einfachere Fehlerbehandlung. Jede Methode in Java muß Ausnahmen entweder explizit abfangen oder weiterleiten. Zum Abfangen kann man try und catch wie folgt benutzen.
try { // open a file ... // read data ... } catch (IOException e) { System.out.println("Couldn't write"); // do the clean up, e.g. closing the file }
Die vollständige Syntax dieser Anweisungsfolge ist:
try { // statements possibly generating // Exception_1 or Exception_2 } catch (Exception_1 e) { // statements handling Exception_1 } catch (Exception_2 e) { // statements handling Exception_2 } ... finally { // statements cleaning up for all the cases }Der finally-Block wird unabhängig vom Auftreten von Ausnahmen zum Schluß ausgeführt.
Zum Weiterleiten von Ausnahmen kann man das throws-Schlüsselwort benutzen. Zum Auslösen von Ausnahmen verwendet man das throw-Schlüsselwort.
public void getInputData() throws MyException { ... if (notOK) { throw new MyException(); } ... }
Zur Definition einer Ausnahme wird eine Subklasse von Exception gebildet.
class MyException extends Exception { public MyException() { ...; } public MyException(String msg) { ...; } }
Wir definieren eine einfache Klasse für Autos (Car). Man kann mit dieser Klasse ein Auto mit den Parametern Modell (model), Baujahr (year) und (Neu-)Preis (price) definieren. Die Klassen-Methoden getModel(), getYear() und getPrice() dienen dem Zugriff auf die Klassen-Parameter.
public class Car { String model; int year; int price; public Car(String m, int y, int p) { model = m; year = y; price = p; } public String getName() { return model+" [year="+year+"]"; } public int getPrice() { return price; } public static void main(String[] args) { Car ford = new Car("ford bronco", 1992, 35000); Car vw = new Car("vw golf", 1984, 25000); System.out.println( ford.getName()+" costs "+ford.getPrice()); System.out.println( vw.getName()+" costs "+vw.getPrice()); } }Mit dieser Klasse kann man zum Beispiel die Objekte ford und vw erzeugen. Dies ergibt dann folgende Ausgabe.
ford bronco [year=1992] costs 35000 vw golf [year=1984] costs 25000
Mit dem Schlüsselwort extends kann man eine Klasse von einer anderen Klasse ableiten. Als Beispiel einer abgeleiteten Klasse von Car sei die Klasse Gebrauchtwagen (UsedCar) definiert, die den zusätzlichen Parameter `gefahrene Kilometer' (mileage) hat.
public class UsedCar extends Car { int mileage; public UsedCar(String m, int y, int p, int k) { super(m, y, p); mileage = k; } public String getName() { return super.getName()+" (mileage="+mileage+")"; } public int getMileage() { return mileage; } public int getPrice() { return 10000*price/(mileage+10000); } }Die Methode getMilage() dient wieder dem Zugriff auf die Klassen-Parameter. Der Konstruktor für UsedCar ruft mit super(m, y, p) den Konstruktor der Basisklasse auf, dann wird der Parameter mileage gesetzt. Die Methode getPrice() überschreibt die Methode mit dem gleichen Namen und der gleichen Signatur (d.h. der gleichen Art und Anzahl der Parameter) von der Basisklasse. getPrice() berechnet in dieser Klasse den Gebrauchtwagenpreis in Abhängigkeit von der gefahrenen Kilometerzahl.
Mit diesen Klassen kann man dann zum Beispiel in dem Hauptprogramm main die folgenden Beziehungen definieren und ausdrucken.
public static void main(String[] args) { Car cars[] = new Car[4]; cars[0] = new Car("ford bronco", 1992, 35000); cars[1] = new UsedCar("ford bronco", 1992, 35000, 8000); cars[2] = new Car("vw golf", 1984, 25000); cars[3] = new UsedCar("vw golf", 1984, 25000, 20000); for (int i=0; i<4; i++) System.out.println(cars[i].getName() +" costs "+cars[i].getPrice()); }
Als Ausgabe erhält man zum Beispiel.
java UsedCar ford bronco [year=1992] costs 35000 ford bronco [year=1992] (mileage=8000) costs 19444 vw golf [year=1984] costs 25000 vw golf [year=1984] (mileage=20000) costs 8333
Eine Java-Klasse ist nur von einer anderen Klasse ableitbar. Java kennt keine Mehrfachvererbung! Aber mit dem Sprachkonstrukt interface kann eine Klasse mehrere Methodensignaturen erben. Ein Interface deklariert nur abstrakte Methoden.
Zum Beispiel kann man ein Interface Rank definieren, das das Vergleichen zweier Objekte erlaubt. compare() gibt eine positive ganze Zahl zurück, falls dieses Objekt (this) in der implementierten Ordnung vor dem anderen Objekt (obj) steht.
public interface Rank { public int compare(Rank obj) throws RankException; }Ist die implementierte Ordnung nicht total, so wird für unvergleichbare Objekte eine RankException ausgelöst.
public class RankException extends RuntimeException { }
Eine Subklasse von Rectangle (aus java.awt), die dieses Interface unterstützt, kann man wie folgt definieren.
public class RankedRect extends Rect implements Rank { public RankedRect(int w, int h) { super(w,h); } public int compare(Rank obj) throws RankException { try { return area() - ((Rect)obj).area(); } catch (ClassCastException e) { throw new RankException(); } } }
In einer ähnlichen Weise kann man eine Subklasse von Car definieren.
public class RankedCar extends Car implements Rank { public RankedCar(String m, int y, int p) { super(m,y,p); } public int compare(Rank obj) { try { return getPrice()-((Car)obj).getPrice(); } catch (ClassCastException e) { throw new RankException(); } } }
Diese beiden Klassen können behandelt werden, als ob sie vom Typ Rank wären. Zum Beispiel als Argument in einer Methode foo(Rank obj). Eine Klasse kann mehrere Interfaces implementieren. Bei der Instanziierung von Klassen, die ein Interface implementieren, kann man die Struktur, die nicht von dem Interface stammt, ignorieren.
Rank r = new RankedCar(model, year, price);Dann ist aber nur noch die Verwendung der Methode r.compare(.) möglich und nicht mehr r.getModel(). Um dennoch getModel() zu verwenden, muß erst ein Cast (eine Typenanpassung) auf RankedCar gemacht werden:
( (RankedCar) r ).getModel()
Man kann eine Klasse definieren, die keine vollständige Implementierung der deklarierten Methoden enthält. Diese kann man sich als Mischform zwischen einem Interface und einer richtigen Klasse vorstellen. Ein Teil der Methoden wird implementiert, und für einen anderen Teil der Methoden werden nur die Spezifikationen (das Interface) festgelegt.
Eine solche Klasse wird als abstrakte Klasse bezeichnet und muß mit dem Schlüsselwort abstract gekennzeichnet werden.
public abstract class Cell { int size; public int getSize() { return size; } public abstract void interact(Cell neighbor); }
Abstrakte Klassen können nicht instanziiert werden (d.h. es kann kein Objekt aus einer abstrakten Klasse erzeugt werden). Eine Subklasse, die die fehlende Implementation definiert, kann instanziiert werden.
Von Klassen, die mit dem Schlüsselwort final deklariert sind, können keine Klassen abgeleitet werden. Dies dient zum einen dazu, unerwünschte Ableitungen zu verhindern, wie zum Beispiel bei system-nahen Klassen java.lang.System. Und sie dienen zum anderen dazu, dem Compiler Hinweise für die Optimierung zugeben, denn es müssen dann keine Vorkehrungen zum Überschreiben dieser Methoden getroffen werden.
kleine eigenständige Anwendung
kann in Web-Browsern mit JVM ausgeführt werden
Programmteile werden übers Netzgeladen
Nutzung der Vorteile der Java Programmiersprache
Nutzung aller APIs von Java soweit aus Sicherheitsgründen erlaubt
Sandkasten Prinzip
insbesondere sind TCP/IP Verbindungen mit eigener Verschlüsselung möglich
Applet Klasse ist von einer AWT Klasse Component abgeleitet
AWT definiert Zeichenfunktionen, Buttons, etc.
Applet definiert zusätzlich Ausführungslogik: init(), start(), stop(), destroy()
package java.applet; import java.awt.*; import java.awt.image.ColorModel; import java.net.URL; import java.net.MalformedURLException; import java.util.Hashtable; import java.util.Locale; public class Applet extends Panel { public boolean isActive() public URL getDocumentBase() public URL getCodeBase() public String getParameter(String name) public AppletContext getAppletContext() public void resize(int width, int height) public void resize(Dimension d) public void showStatus(String msg) public Image getImage(URL url) public Image getImage(URL url, String name) public final static AudioClip newAudioClip(URL url) public AudioClip getAudioClip(URL url) public AudioClip getAudioClip(URL url, String name) public String getAppletInfo() public Locale getLocale() public String[][] getParameterInfo() public void play(URL url) public void play(URL url, String name) public void init() public void start() public void stop() public void destroy() }
public class Panel extends Container ... public class Container extends Component public class Component extends Object implements ... { public void paint(Graphics g) { } ... }
Übergabe des Parameters 'nachricht' und Zeichnung des Textes in 'paint'.
import java.awt.*; import java.applet.*; public class HelloWorldApplet extends Applet { String msg = ""; public void init () { msg = getParameter("nachricht"); } public void paint(Graphics g) { g.drawString("Hello World ...",10,50); g.drawString(msg,10,75); g.drawString("... vom Applet.",10,100); } }
Einbettung in HTML mit dem Applet-Element.
<applet code="HelloWorldApplet.class" width="150" height="150"> <param name="nachricht" value="mit Parameter"> </applet>
Erweiterung der Web-Server Funktionalität
kann CGI ersetzen, bzw. ergänzen
Einbindung via Server-API oder Standalone
Nutzung der Vorteile der Java Programmiersprache
Nutzung aller APIs von Java
Apache: JServ, Jacarta Projekt
Integration in Java-Web-Server: Jigsaw
Websphere von IBM, JRun von Live Software, etc
Kombination mit Java Server Pages (JSP)
z.Z. Version 2.2., vom 17. Dez. 1999
Web-Application Konzept
Basis Funktionalität: Kontextverwaltung, Sende- und Empfangs-Objekte, Service-Methode
und eine an CGI angelehnte Schnittstelle: Http, Cookies, Sitzungsverwaltung
Basis Interfaces: Servlet
,
ServletConfig
, ServletContext
,
ServletRequest
, ServletResponse
Abstrakte Klassen: GenericServlet
,
ServletInputStream
, ServletOutputStream
HTTP Interfaces:
HttpServletRequest
, HttpServletResponse
,
HttpSession
, HttpSessionContext
(Abstrakte) Klassen: HttpServlet
, Cookie
Es wird im Web-Server nur ein Servlet-Objekt erzeugt, nicht für jede Anfrage ein neues
Beachte Multithreading: service
, doGet
können parallel aufgerufen werden
package javax.servlet; public interface Servlet { public void init(ServletConfig config) throws ServletException; public ServletConfig getServletConfig(); public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public String getServletInfo(); public void destroy(); }
public interface ServletConfig { } public interface ServletRequest { public int getContentLength(); public ServletInputStream getInputStream() throws IOException; .... } public interface ServletResponse { public ServletOutputStream getOutputStream() throws IOException; public void setContentType(String type); ... }
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { public void init(ServletConfig config) throws ServletException public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; ... }
import java.io.*; import java.text.*; import java.util.*; import javax.servlet.*; public class SimpleHelloWorld extends GenericServlet { private int aufrufe; public void init(ServletConfig config) throws ServletException { super.init(config); aufrufe=0; } public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); out.println("<html>"); out.println("<body bgcolor=\"white\">"); out.println("<head>"); String title = "Hello World"; aufrufe++; out.println("<title>" + title + "</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>" + title + "</h1>"); out.println("<h2>" + aufrufe + " Aufrufe</h2>"); out.println("</body>"); out.println("</html>"); } }
package javax.servlet.http; public abstract class HttpServlet extends GenericServlet implements java.io.Serializable { public HttpServlet() protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException protected long getLastModified(HttpServletRequest req) private void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException ... }
import java.io.*; import java.text.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorldExample extends HttpServlet { ResourceBundle rb = ResourceBundle.getBundle("LocalStrings"); public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<body bgcolor=\"white\">"); out.println("<head>"); String title = rb.getString("helloworld.title"); out.println("<title>" + title + "</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>" + title + "</h1>"); out.println("</body>"); out.println("</html>"); } }
Einbettung von Java in HTML
wie PHP oder ASP
Kennzeichnung durch <% Java Code %>
aus dem Java Code wird beim ersten Aufruf ein Servlet
generiert und dieses dann compiliert (javac
)
die Ausführung des Byte-Code ist dann wesentlich schneller
der Web-Server wird konfiguriert,
dass Dateien mit bestimmter Endung (*.jsp
)
von dem JspServlet
behandelt werden
Import von Java Klassen mit
<%@ import "java.util.Date" %>
Einfügen von anderen Dateien
<%@ include file="dateiname" %>
Zugriff auf Variablen der
service
-Methode von Servlet
Einfügen von Variablen und Ausdrücken in HTML mit '='
<%= var.name; %>
Zugriff auf JSP-Teile im XML Stil
<jsp:expr> request.getQueryString() </jsp:expr>
Deklarationen mit '!'
<%! int xyz = 1; %>
Definition eigener Tags
<%@ taglib="URL" prefix="my" %>
Verwendung von Java Beans möglich
<jsp:usebean id="." class="xyz" >
<html> <head> <title>Hello World JSP</title> </head> <body bgcolor="white"> <hr> <% out.println("<h2>Hallo Welt! von JSP</h2>"); %> <hr> </body> </html>
ideale Programmiersprache und Entwicklungsumgebung fürs Web
Applets erweitern die Möglichkeiten der Browser (UAs)
Servlets erweitern die Möglichkeiten der Web-Server
Java Beans
Swing
Java Web-Applications
© Universität Mannheim, Rechenzentrum, 1998-2000.
Heinz Kredel Last modified: Sun Oct 1 19:11:41 MEST 2000