Ein erster Eindruck von Aussehen, Benutzung und Möglichkeiten von Java.
Zwei Einsatzbereiche:
Java-Programme werden interpretiert:
Im JDK ( Java Development Kit) von Sun sieht die Übersetzung und Ausführung von Applikationen so aus:
javac Diesel.java javac Motor.java java Diesel
falls Diesel das Hauptprogramm enthält.
Wichtige Regel:
Der Name der Datei (Übersetzungseinheit) ohne das ``.java'' muß gleich dem Namen der in der Datei definierten öffentlichen Klasse sein.
Jede Klasse in einer ``.java''-Datei führt beim Übersetzen
zu einer eigenen ``.class''-Datei.
Dadurch:
Automatisierung des Übersetzungsprozesses:
Wenn Diesel Motor benutzt, etwa durch
class Diesel extends Motor { ... }
führt das Kommando
javac Diesel.java
automatisch auch zur Übersetzung von Motor (wenn nötig).
Applets leben in Web-Seiten. Die Applet-Zwischencode-Datei
( Bytecode)
wird im HTML-Text angegeben:
<html> <head> <title> Motor Applet </title> </head> <body> <applet code=Motor.class width=260 height=260> </applet> </body> </html>
Der Interpretierer ist im Browser integriert und wird von diesem
aufgerufen.
Andere Möglichkeit:
Der appletviewer aus dem JDK:
appletviewer slider.html
// Datei HelloWorld.java class HelloWorld { public static void main(String[] args) { System.out.println("Hello, world"); } }
javac HelloWorld.java java HelloWorld
class Fibonacci { public static void main(String[] a) { int lo = 1; int hi = 1; System.out.println(lo); while (hi < 500) { System.out.println(hi); hi = lo + hi; lo = hi - lo; } } }
Beispiel:
/** * Konstruktor mit Größenangabe */ schraubenschlüssel(int sz) { .... }
In Java bekommt man benannte Konstanten durch finale
Klassenvariablen:
class ZylinderZahl { final static EINZYLINDER = 1; final static ZWEIZYLINDER = 2; final static DREIZYLINDER = 3; }
static bedeutet: dies ist ein Attribut der Klasse (nicht von individuellen Objekten)
final bedeutet: dieses Attribut erhält hier seinen endgültigen Wert.
Benutzung außerhalb von ZylinderZahl wird qualifiziert mit dem Klassennamen:
if (zyl == ZylinderZahl.EINZYLINDER) { .... }
class Motor() { public int rpm; // rounds per minute public void on() // Motor anmachen { ... } }
Es gibt neben public noch 4 Stufen der Sichtbarkeit von Attributen und Methoden:
Zugriff immer über Referenzen ( Referenzsemantik).
Garbage Collection (GC): automatische
Entsorgung von Objekten, die nicht mehr gebraucht werden.
In Java läuft der Garbage Collector im Hintergrund immer mit.
Manchmal sollen sich alle Objekte einer Klasse auch ein Attribut teilen. Ein solches Attribut beschreibt dann Eigenschaften der Klasse.
class WerkstattKunde { public static int KundenZahl; ... }
Kundenzahl ist Eigenschaft der Klasse. Alle Objekte der
Klasse WerkstattKunde teilen sich dieses Attribut.
Situation, wo man diese Selbstreferenz braucht:
public void on () { this.glüh(); // 'glüh()' reicht auch super.on(); // geht nicht ohne 'this': läuft.addtolist(this); }
Arbeiten auf Eigenschaften der Klassen, nicht auf individuellen Objekteigenschaften.
class WerkstattKunde { public static void incKundenZahl() { KundenZahl++; } }
Der zweite nicht-primitive Datentyp in Java neben Objekten.
Wie bei Objekten gilt:
Motor Prüfstand[] = new Motor[10];
Jedes Array hat ein konstantes length-Attribut, das die Anzahl der Array-Elemente angibt:
for (index = 0; index < Prüfstand.length(); index++) asu.motor_check(Prüfstand[index]);
In Java findet grundsätzlich Bereichsprüfung für Array-Zugriffe
statt.
Trotzdem ( !) gibt es in Java
"Hello, world"
)
class WerkstattKunde { WerkstattKunde (String name) { String kname = "knd_" + name + "_" + String.valueOf (KundenZahl); ... } }
Wichtig: Strings sind unveränderlich ( immutable).
Änderbare gibt es in der Klasse StringBuffer.
Eine Klasse, die eine andere erweitert, erbt die Attribute und Methoden der Oberklasse.
class Diesel extends Motor { public Diesel(String n) { super(n); // Oberklassenkonstruktor } public void on() { System.out.print("Diesel "); glueh(); super.on(); // Oberklassen-on() } private void glueh() { System.out.print("vorglühen"); } }
Möglichkeiten der Klassenerweiterung:
Wörterbuch
erweitern | extend |
verstecken | hide |
überladen | overload |
überschreiben | override |
Reine Beschreibung des Entwurfs von Objekten. Vollständig abstrahiert von der Implementierung.
Entspricht abstrakten Klassen (ohne Attribute) in anderen OO-Sprachen.
Der Entwerfer von Schnittstellen spezifiziert, welche Methoden von
Klassen, die die Schnittstelle implementieren, bereitgestellt
werden.
interface Ersetzbar { // für ersetzbare Objekte läßt sich // eine Ersatzteilnummer ermitteln: int ersatzteilnummer(String Name); }
Java-Klassen können mehrere Schnittstellen implementieren:
class Motor implements Ersetzbar, Identifizierbar { ... }
Schnittstellen können wie Klassen verwendet werden:
// Bestelle beim Großhändler alle // benötigten Ersatzteile pubic static void ersatzteilorder(Ersetzbar[] kaputt) { ... }
Schnittstellen können andere Schnittstellen erweitern (auch mehrere):
interface DruckbarUndSpeicherbar extends Druckbar, Speicherbar { boolean aktuelleversiongedruckt(); }
Interfaces erweitern die Möglichkeiten der Polymorphie:
Die Obertypen einer Klasse T
umfassen
Ein Objekt vom Typ T darf überall dort verwendet werden, wo Obertypen
von T zulässig sind.
Wenn eine Ausnahme nicht im Block behandelt wird, wo sie erzeugt wird, propagiert sie in den umfassenden Block, dann in die aufrufenden Methode, usw. bis zur main-Methode.
Wird sie auch dort nicht
behandelt, erzeugt der Java-Interpretierer eine Fehlermeldung und
beendet die Ausführung.
Beispielprojekt: Fakultätsprogramm
Ziel:
Wir lernen:
Wir brauchen:
Die Fakultätsberechnung
/** Fac.java * Implementiert die Fakultätsfunktion * rekursiv. * Arg./Erg.: long (64bit signed integer) * Überprüft Fehler */ public class Fac { static final long maxarg = 20; public static long fac (long x) throws IllegalArgumentException { if (x < 0) throw new IllegalArgumentException ("negativ: " + x); if (x > maxarg) throw new IllegalArgumentException ("zu groß: " + x); if ( x == 0) return 1; else return x * fac(x-1); } }
Das Fakultäts-Hauptprogramm
/** facmain.java * Fakultätsprogramm mit * Kommandozeilen-Eingabe */ public class Facmain { public static void main (String[] args) { // Versuche, die Fakultät zu berechnen try { int x = Integer.parseInt(args[0]); System.out.println(x + "! = " + Fac.fac(x)); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Argument fehlt!");} catch (NumberFormatException e) { System.out.println ("Argument ist keine ganze Zahl!");} catch (IllegalArgumentException e) { System.out.println ("Ungültiges Argument: " + e.getMessage());} } }
Java benutzt Pakete zur Organisation des Namensraumes.
Ein Paket
Die Paket-Hierarchie führt in voll-qualifizierter Schreibweise zu langen Typnamen:
java.util.Date today = new java.util.Date();
import-Klauseln bringen Schreiberleichterung:
import java.util.Date; // eine Klasse import java.applet.* // alles ... Date today = new Date();
Die Zugehörigkeit zu einem Paket spezifiziert man in der 1. Anweisung
einer Übersetzungseinheit:
package werkstatt.buchhaltung;
Ohne package-Anweisung gehört eine Klasse zu einem anonymen
Default-Paket. Das ist praktisch für kleine Tests oder während der
Entwicklung.
Java legt nicht fest, wie Pakete organisiert werden. Die meisten Java-Umgebungen bilden die Paket-Hierarchie auf die Directory-Struktur des Filesystems ab.
Java findet Klassen dann
UNIX:
setenv CLASSPATH .:/home/peter/werkstatt
WINDOWS:
setenv CLASSPATH .;c:\javaprogs\werkstatt
CLASSPATH kann statt Verzeichnissen auch zip-Dateien angeben:
setenv CLASSPATH .:/home/jtools/cls.zip