Kapitel 2 Java: Der Einstieg

Werbung
Kapitel 2
Java: Der Einstieg
Im vorigen Kapitel haben wir die Syntax der Sprache Mini-Java kennengelernt. Bevor wir in Kapitel 3 ausführlich auf Syntax und Semantik der Programmiersprache Java eingehen werden, soll dieses Kapitel zunächst einige grundlegende Vorbemerkungen zu Java machen,
sowie zu den beiden zugrundeliegenden Sprachkonzepten, der imperativen und der objektorientierten Programmierung.
2.1
2.1.1
Grundlegendes zu Java
Historisches
• 1990-1991: Entwicklung der Programmiersprache OAK durch James Gosling von Sun Microsystems (zunächst für Toaster, Mikrowellen etc.; unabhängig vom Chip, extrem zuverlässig)
• Umbenennung in Java
• 1995: α und β Release
• von IBM, SGI, Oracle und Microsoft lizensiert
2.1.2
Eigenschaften von Java
• durch den Bytecode (Zwischensprachencode) unabhängig von der Plattform
• Syntax an C und C++ angelehnt
• im Gegensatz zu C und C++ vollständig spezifiziert
• objektorientiert
• streng typisiert
19
• unterstützt parallele Abläufe (Nebenläufigkeit / Threads)
• Graphical User Interface (GUI)
• netzwerkfähig
• modularer Aufbau
• Nachteil: Effizienz leidet (ca. 5–10mal langsamer als C und C++)
Selbstständig
laufende
Anwendung
Quellprogramm
Java-Compiler
!
Java-Bytecode auf dem Server
Java-Interpreter
!
Ablauf des Programms
Applet
Quellprogramm
Java-Compiler
!
Java-Bytecode auf dem Server
Übertragung per Internet
!
Bytecodes auf dem Rechner
des Benutzers (Client)
Java-Interpreter im Browser
oder Applet-Viewer
!
Ablauf des Programms
Abbildung 2.1: Vom Quellprogramm zum Ablauf
Abbildung 2.1 zeigt die notwendigen Schritte, um ein Java-Programm (selbstständig laufende Anwendung) bzw. ein Applet ablaufen zu lassen. Ein Applet
ist eine in ein HTML-Dokument eingebettete Anwendung, die auf dem Rechner
des Anwenders abläuft. Wir beschränken uns in diesem Skript auf selbstständig
laufende Anwendungen.
20
2.1.3
Sicherheit
• keine Pointerarithmetik wie in C
• Garbage Collection1
• Überprüfungen zur Laufzeit (Datentypen, Indizes, etc.) durch Mechanismen
zur Verifizierung von Java-Bytecode bei der Übertragung
• dennoch ist die (Netz-)Sicherheit umstritten
2.1.4
Erstellen eines Java-Programms
1. Quellprogramm erstellen:
class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
Dieses Programm besteht aus der Klasse Hello. Der Klassenname muss
mit dem Dateinamen übereinstimmen, d.h. das oben gezeigte Programm
muss in der Datei Hello.java abgelegt sein. Die Klasse Hello enthält eine Methode namens main. Ein Java-Programm muss eine main-Methode
enthalten, denn die main-Methode wird bei der Interpretation aufgerufen.
2. Übersetzen eines Programms:
> javac Hello.java
liefert eine Datei Hello.class, die das Programm in Bytecode enthält.
3. Interpretation des Bytecodes:
> java Hello
Ein Garbage Collector entfernt automatisch Objekte, Felder und Variablen, auf die keine
Referenz mehr vorhanden ist, aus dem Speicher (siehe Arnold & Gosling [1], S. 12, Kapitel 1.6).
1
21
2.2
2.2.1
Grundzüge imperativer Sprachen
Das Behältermodell der Variablen
Imperative Programmierung geht aus vom Modell eines Speichers, aufgegliedert
in einzelne Variablen, in denen Werte abgelegt werden können. Der Speicher bzw.
die Variablen werden verändert durch Befehle bzw. Anweisungen, die selbst vom
aktuellen Speicherinhalt abhängen. Ein typisches Beispiel ist die Anweisung
x = y + z.
Sie bedeutet: Addiere die Variableninhalte von y und z und lege die Summe in
der Variablen x ab. Während diese Semantikbeschreibung nun suggeriert, dass
der einzige Effekt der Anweisung eine Änderung des Variableninhalts von x ist,
ist in der Tat diese Vorstellung zu einfach:
• nicht nur der Variableninhalt von x kann sich ändern, sondern auch der von
y und z sowie aller möglicher anderer Variablen;
• falls x ≡ y oder y ≡ z, dann ist dies unmittelbar einsichtig.
Also ist “x = y + z” keine Gleichheit, die zwischen den Werten (Inhalten) von
x, y und z gilt, und mittels der wir über Programme nachdenken und Beweise
führen können. Das Prinzip der referential transparency“ (Werttreue), das in der
”
funktionalen Programmierung gilt, ist in der imperativen verletzt.
2.2.2
Konsequenzen
1. Der Nachweis von Programmeigenschaften wird viel schwieriger, ebenso das
Verstehen von Programmen.
2. Die Semantik eines Programms hängt von einem strikten Nacheinander der
Ausführung der einzelnen Anweisungen ab.
3. Wiederverwendung von Programmteilen in anderem Kontext bedarf besonderer Vorsicht.
2.3
Klassen, Objekte und Methoden im Überblick
Java-Programme werden aus Klassen aufgebaut. Aus einer Klassendefinition lassen sich beliebig viele Objekte erzeugen, die auch Instanzen genannt werden (vgl.
Arnold & Gosling [1], Kapitel 1.6 und 1.7).
22
Eine Klasse enthält folgende Bestandteile:
• Objektvariablen (objektbezogene Datenfelder)
• objektbezogene Methoden
• Klassenvariablen (klassenbezogene Datenfelder)
• klassenbezogene Methoden
Datenfelder (Synonym: Attribute) enthalten den Zustand des Objektes oder der
Klasse. Methoden sind Sammlungen von imperativ formulierten Anweisungen,
die auf den Datenfeldern operieren, um deren Zustand zu ändern.
2.3.1
Klassen
Beispiel der Deklaration einer einfachen Klasse:
class Point {
double x, y;
}
In der Klasse Point sind zwei Objektvariablen deklariert, die die x- und yKoordinate eines Punktes repräsentieren. double bedeutet, dass die Variablen
vom Typ double2 sind. Bis jetzt gibt es noch kein Objekt vom Typ Point, nur
einen “Plan”, wie ein solches Objekt aussehen wird.
2.3.2
Das Erzeugen von Objekten
Objekte werden mit dem Schlüsselwort new erzeugt. Neu geschaffene Objekte
bekommen innerhalb eines Bereiches des Speichers (welcher Heap genannt wird)
einen Speicherplatz zugewiesen und werden dort abgelegt. Auf alle Objekte in
Java wird über Objektreferenzen zugegriffen – jede Variable, die ein Objekt zu
enthalten scheint, enthält tatsächlich eine Referenz auf dieses Objekt (bzw. auf
deren Speicherplatz). Objektreferenzen haben den Wert null, wenn sie sich auf
kein Objekt beziehen. Wir werden im folgenden Objekte und Objektreferenzen
synonym verwenden, es sei denn, die Unterscheidung ist wichtig.
Erzeugung und Initialisierung
Point lowerLeft = new Point();
Point upperRight = new Point();
2
Gleitkommazahlen
23
Wertzuweisung
lowerLeft.x = 0.0;
lowerLeft.y = 0.0;
upperRight.x = 1280.0;
upperRight.y = 1024.0;
2.3.3
Klassenvariablen
class Point {
double x, y;
static Point origin = new Point();
}
Wird eine Variable als static deklariert, so handelt es sich um eine Klassenvariable. Durch obige Deklaration gibt es genau eine Klassenvariable names Point.origin,
egal ob und wie viele Point-Objekte erzeugt werden. Point.origin hat den Wert
(0,0), weil dies die Voreinstellung für numerische Datenfelder ist, die nicht explizit auf einen anderen Wert initialisiert werden (das wird später noch genauer
besprochen). Allerdings kann der Wert von Point.origin geändert werden. Ist
dies nicht erwünscht, soll Point.origin also eine Konstante sein, so muss man
den Modifizierer final benutzen.
static final Point origin = new Point();
2.3.4
Methoden
Eine Methode ist eine Funktion bzw. Prozedur. Sie kann parameterlos sein oder
Parameter haben. Sie kann einen Rückgabewert liefern oder als void deklariert
sein, wenn sie keinen Wert zurückliefert. Methoden dürfen nicht geschachtelt werden. Innerhalb von Methoden dürfen lokale Variablen deklariert werden.
class Point {
double x, y;
void clear() {
x = 0.0;
y = 0.0;
}
}
Um eine Methode aufzurufen, gibt man ein Objekt und den Methodennamen,
getrennt durch einen Punkt, an.
24
lowerLeft.clear();
upperRight.clear();
Nun definieren wir eine Methode, die die Distanz zwischen dem Punkt, auf den
sie angewendet wird und einem übergebenen Punkt p zurückgibt. (Math.sqrt()
ist vordefiniert und liefert die Wurzel einer Zahl.)
double distance(Point p) {
double xdiff, ydiff; // Beispiel fuer lokale Variablen
xdiff = x - p.x;
ydiff = y - p.y;
return Math.sqrt(xdiff*xdiff + ydiff*ydiff);
}
Aufruf: double d = lowerLeft.distance(upperRight);
2.3.5
Klassenbezogene Methoden
Klassenbezogene Methoden werden durch das Schlüsselwort static deklariert,
z.B. ist Math.sqrt() eine Klassenmethode der vordefinierten Klasse Math.
“distance” als Klassenmethode
static double distance(Point p1, Point p2) {
double xdiff = p1.x - p2.x;
double ydiff = p1.y - p2.y;
return Math.sqrt(xdiff*xdiff + ydiff*ydiff);
}
Aufruf: double d = Point.distance(lowerLeft, upperRight);
In der Klasse Point selbst kann man Point. weglassen, d.h. es reicht ein Aufruf
der Form: double d = distance(lowerLeft, upperRight);
2.4
2.4.1
Vererbung, Pakete und Gültigkeitsbereiche
Vererbung
Klassen in Java können um zusätzliche Variablen und Methoden erweitert werden. Dies wird durch das Schlüsselwort extends angezeigt. Die entstehende Unterklasse besitzt dann alle Eigenschaften der Oberklasse und zusätzlich die in der
jeweiligen Erweiterung angegebenen Eigenschaften. Dieses Konzept wird auch als
Vererbung bezeichnet, weil die Unterklasse alle Eigenschaften der Oberklasse erbt.
Zum Beispiel ist ein farbiger Punkt eine Erweiterung eines Punktes:
25
class ColoredPoint extends Point {
String color;
}
2.4.2
Pakete
Bei größeren Softwareprojekten ist es häufig ratsam, diese in verschiedene, unabhängige Teile aufzuteilen. Solche Teile werden als Module oder Pakete bezeichnet.
Java besitzt einige Eigenschaften, die es erlauben, Software modular aufzubauen:
Verschiedene (i.d.R. logisch zusammengehörige) Klassen können in einem Paket
zusammengefasst werden. Die Klassendefinitionen können in verschiedenen Dateien enthalten sein.
Der Paketname muss im Header jeder Datei angegeben sein:
A.java
C.java
package abc;
public class A {
...
}
package abc;
class C {
...
}
class B {
...
}
Um Definitionen aus anderen Paketen sichtbar zu machen, müssen sie mit dem
Schlüsselwort import importiert werden:
import abc.A;
class test {
A a;
}
Weitere Details zu Paketen folgen in Kapitel 7.2.
2.4.3
Gültigkeitsbereiche
Bei dem Zugriff auf Definitionen anderer Klassen oder Pakete gelten Beschränkungen, die beachtet werden müssen. Die Zugriffsrechte werden durch Gültigkeitsmodifizierer geregelt, die sich folgendermaßen auf Datenfelder, Methoden
und Klassen auswirken (für Klassen gibt es nur public und default):
26
zugreifbar für Nicht-Unterklassen
im selben Paket
zugreifbar für Unterklassen im
selben Paket
zugreifbar für Nicht-Unterklassen
in einem anderen Paket
zugreifbar für Unterklassen in
einem anderen Paket
2.5
public
ja
default (package)
ja
protected
ja
private
nein
ja
ja
ja
nein
ja
nein
nein
nein
ja
nein
ja
nein
Aufgaben
Aufgabe 2.5.1 Erstellen Sie eine Klasse Circle, deren Instanzen Kreise im
zweidimensionalen Raum repräsentieren. Ein Kreis ist z.B. bestimmt durch seinen
Radius r und durch die x- und y-Koordinate seines Mittelpunktes in der Ebene.
Implementieren Sie für diese Klasse folgende Methoden:
(i) circumference berechnet den Umfang des Kreises.
(ii) area berechnet den Inhalt des Kreises.
Wie können die Methoden in einem Programm aufgerufen werden?
27
28
Herunterladen