1.03k likes | 1.27k Vues
Klassen und höhere Datentypen. Objekte, Felder, Methoden, Ausnahmeobjekte, Reihungen, Listen, Stapel. Foliensatz von A. Weber zur Vorlesung Informatik I, Bonn, 2002/03 Überarbeitet von W. Küchlin zu Informatik I, Tübingen 2003/04. Objekte, Felder, Methoden. Klassen.
E N D
Klassen und höhere Datentypen Objekte, Felder, Methoden, Ausnahmeobjekte, Reihungen, Listen, Stapel Foliensatz von A. Weber zur Vorlesung Informatik I, Bonn, 2002/03 Überarbeitet von W. Küchlin zu Informatik I, Tübingen 2003/04 W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -1- Springer-Verlag, ISBN 3-540-20958-1
Objekte, Felder, Methoden W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -2- Springer-Verlag, ISBN 3-540-20958-1
Klassen • Eine Klasse(class) stellt einen (i. a. benutzerdefinierten) zusammengesetzten Datentyp dar • Subtile Unterscheidung: Typ ist abstraktes Konzept, durch die Spezifikation gegeben, Klasse ist die Implementierung eines Typs. • Es kann mehrere Implementierungen eines Typs geben • Für uns hier unwesentlich • Datentyp ist implementiert durch • Objekte (heißen auch Instanzen (instances) der Klasse) • Jedes Objekt hat individuellen Datensatz (Zustand), gespeichert in Instanzvariablen (instance variables). Heißen in jedem Objekt gleich, haben aber i.a. verschiedene Werte. • Instanzmethoden (werden auf einem Objekt aufgerufen, laufen auf diesem, haben Zugriff auf die Instanzvariablen des Objekts) • Klassenvariablen (nur ein Satz pro Klasse, speichern globalen Zustand der Klasse) • Klassenmethoden (werden wie normale Funktionen aufgerufen, unabhängig von Objekten) • Klasse bedeutet zweierlei • dynamisch: Menge aller Objekte dieses Typs • statisch: Deklaration, wie Objekte dieses Typs aufgebaut sind (Instanzvariablen und Instanzmethoden) und welche Klassenvariablen und –Methoden es gibt. W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -3- Springer-Verlag, ISBN 3-540-20958-1
Klassen • Eine Klassendeklaration spezifiziert die Bestandteile (Mitglieder, members), im Wesentlichen Variablen, in Java Felder (fields) genannt, und Methoden (methods) • die Instanzvariablen (instance variables, non-static fields) • aus denen sich Objekte des Typs zusammensetzen • Auch Attribute genannt • die Konstruktoren(constructors), mit denen neue Objekte des Typs initialisiert werden • die Instanzmethoden(instance methods, non-static methods) des Datentyps • die auf den Objekten operieren • Auch Mitgliedsfunktionen (member functions) genannt • die Klassenvariablen (static fields) • die Klassenmethoden (static methods) W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -4- Springer-Verlag, ISBN 3-540-20958-1
Objekte, Felder und Methoden • Ein Objekt(object) ist eine Instanz(instance) einer Klasse • Bei der Erzeugung eines Objekts (mit new) wird auf der Halde (heap) ein passendes Stück Speicher angelegt (allocate), auf dem neue Inkarnationen der Felder eingerichtet werden • Jedes Objekt hat also eigene Werte für die in der Klasse spezifizierten Datenfelder • Als Methoden hat es die Instanzmethoden seiner Klasse • Diese werden jeweils beim Aufruf an ein Objektgebunden und operieren auf diesem Objekt • Wenn sie ein Feld einer Klasse erwähnen, dann ist für die Dauer des Aufrufs die Inkarnation des Feldes im gebundenen Objekt gemeint • Die eben beschriebenen Felder und Methoden heißen deshalb auch Instanzvariablen(instance variables) und Instanzmethoden(instance methods) • Daneben gibt es auch Klassenvariablen(class variables) und Klassenmethoden(class methods), die nicht an Objekte gebunden sind • Diese stellen eher Sonderfälle dar, die wir später noch behandeln • Im Normalfall meinen wir mit Feldern und Methoden immer Instanzvariablen und Instanzmethoden W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -5- Springer-Verlag, ISBN 3-540-20958-1
Klassendeklaration • Die Klassendeklaration beginnt mit dem Schlüsselwortclass gefolgt vom Namen der Klasse • Per Namens-Konvention werden Klassennamen immer (auch in Englisch) großgeschrieben • Soweit die verwendeten UNICODE-Buchstaben zwischen Groß- und Kleinschreibung zu unterscheiden gestatten W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -6- Springer-Verlag, ISBN 3-540-20958-1
Klassendeklaration: Beispiele (1) W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -7- Springer-Verlag, ISBN 3-540-20958-1
Wir deklarieren eine Klasse Time für den Gebrauch in einer elektronischen Stoppuhr Die Instanzmethode tick implementiert die Operation des Tickens des Sekundenzählers Klassendeklaration: Beispiele (3) class Time { int sec=0; // seconds, 0 <= sec < 60 int min=0; // minutes, 0 <= min < 60 int hrs=0; // hours, 0 <= hrs void tick() { sec++; if ( sec >= 60 ) { sec -= 60; min++; if ( min >= 60 ) { min -=60; hrs++; } } } } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -8- Springer-Verlag, ISBN 3-540-20958-1
Wir deklarieren eine Klasse M2DT, die einen Messwert2D mit dem Zeitpunkt (gerechnet seit Beginn des Experiments) verbindet, zu dem er gemessen wurde Wie immer bei Variablen vom Typ einer Objektklasse sind m und t Referenzvariablen Jedes Objekt vom Typ M2DT enthält also zwei Referenzen auf die Teilobjekte, die es verbindet Der Konstruktor M2DT() initialisiert ein neues Objekt des Typs M2DT Klassendeklaration: Beispiele (2) class M2DT { Messwert2D m; // 2-D Messwert Time t; // Zeitpunkt des Messens M2DT() { // Konstruktor m = new Messwert2D(); t = new Time(); } } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -9- Springer-Verlag, ISBN 3-540-20958-1
Deklaration von Variablen mit Klassentyp • Sei Kder Name einer Klasse. Dann istK v;die Deklaration einer Variablenv vom Typ K • Der Ausdruck new K()erzeugtein neues Objekt vom Typ K und sein Wert ist die Referenz auf dieses Objekt;v = new K(); weist diese Referenz anschließend an v zu. • Ganz präzise gesprochen wäre der Typ von v also „Referenz auf K“ • Da in Java aber alleVariablen, deren Typ eine Klasse ist, automatisch Referenz-variablen sind, sagt man einfacher und abkürzend „v hat den (Klassen-) Typ K“ • Ebenso identifiziert man manchmal die Variable mit dem Objekt, obwohl dies verschiedene Dinge sind • Als Nebeneffekt der Ausführung von new wird das neue Objekt initialisiert • Anschließend kann man auf die Attribute von v mittels des Punkt-Operators . zugreifen W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -10- Springer-Verlag, ISBN 3-540-20958-1
Zugriff auf Instanz-Variablen und -Methoden • Eine Instanzvariable wird folgendermaßen angesprochen Klassenobjekt.Variablenname • Eine Instanzmethode wird folgendermaßen aufgerufen Klassenobjekt.Methodenname(arg1, ..., argn) Time t = new Time(); t.sec = 21; // Setze sec in t auf 21 t.min = 35; // Setze min in t auf 35 t.hrs = 2; // Setze hrs in t auf 2 t.tick(); // Rufe tick() auf Objekt t auf W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -11- Springer-Verlag, ISBN 3-540-20958-1
Zugriff auf Instanz-Variablen und -Methoden • Ist d eines der Datenfelder von Objekten vom Typ K, so ist v.d das entsprechende Feld im Objektv • Ist m() eine (Instanz-)Methode von K, so wird m() durch v.m() auf dem Objekt v aufgerufen • Oft verwendet man hier die Metapher der Nachricht(message): v.m() schickt die Nachricht an v, die Methode m() auszuführen • Der Methodenaufruf ist aber eine synchrone Kommunikation, siehe Kapitel über objektorientierte Analyse • Die Prozedur oder Funktion m() kann (wie tick() im Beispiel) auf Felder von KBezug nehmen • Bei einem Aufruf v.m() sind dann die Felder des Objekts v gemeint, bei w.m() die entsprechenden Felder von w W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -12- Springer-Verlag, ISBN 3-540-20958-1
Um eine (Instanz-)Methode an ein Objektbinden zu können bekommt jede Methode der Klasse K vom Java-Übersetzer implizit einen zusätzlichenformalenParameter namens this vom Typ K Diesem Parameter wird die aktuelle Objektreferenz zugewiesen, auf dem die Methode aufgerufen wurde Wird in m() ein Feld d von K erwähnt, so istdamit also this.d gemeint, und innerhalb des Aufrufs v.m() bezeichnet this.d das Feld d des Objekts v Beispiel: Die Methode void tick() der Klasse Time wird implizitergänzt zu: Zugriff auf Instanz-Variablen und -Methoden void Time_tick(Time this) { this.sec++; if( this.sec >= 60 ) { this.sec -= 60; this.min++; if( this.min >= 60 ) { this.min -=60; this.hrs++; }}} Der Aufruf t.tick() entspricht dann Time_tick(t). W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -13- Springer-Verlag, ISBN 3-540-20958-1
Überladen von Methoden • Objektorientierte Programmiersprachen erlauben üblicherweise das Überladen(overloading) von Methodennamen • Ein Methodenname ist in einer Klasse überladen, falls es in der Klasse mehrere Methoden mit dem gleichen Namen (aber unterschiedlicher Signatur) gibt • Dies ist eine Übertragung eines Konzepts, das wir von Funktionenschon kennen • Gibt es zu einem Aufruf mehrere passende Methodendeklarationen, so wird davon die speziellste ausgewählt • Ist diese nicht eindeutig bestimmt, ist der Aufruf unzulässig W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -14- Springer-Verlag, ISBN 3-540-20958-1
Überladen von Methoden • Beispiel: Sei ein Aufruf a.plus(5) gegeben und es existieren Methoden plus(int) und plus(float) in der Klasse, zu der a gehört • Beide Methoden sind anwendbar, aber die erste Methode ist spezieller • Bei Methoden mit mehreren Parametern kann es zu einem Gleichstand kommen • Bemerkung: Wir werden komplizierte Überladungen von Methoden vermeiden und meist nur Konstruktoren überladen • Siehe später W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -15- Springer-Verlag, ISBN 3-540-20958-1
Klassenvariable und Klassenmethoden • Bisher waren die Werte der in der Klasse deklarierten Felder in jedem Objekt (i.a. verschieden) gespeichert und alle Methoden waren implizit mit einem Objektparametrisiert • Ist ein Feld als static deklariert, so sprechen wir von einer Klassenvariable(class variable) und dieses Feld ist nur ein einziges Mal in der Klasse repräsentiert • Egal wie viele Objekte dieser Klasse instanziiert wurden • Ist eine Methode als static deklariert, so sprechen wir von einer Klassenmethode(class method) W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -16- Springer-Verlag, ISBN 3-540-20958-1
Klassenvariable und Klassenmethoden • Klassenmethoden sind nicht durch den verborgenen this Parameter mit einem Objektparametrisiert • Die Methode kann dann auch nicht auf einem Objekt aufgerufen werden, sondern der Aufruf ist von der ArtKlassenname.Methodenname(. . . )oder einfachMethodenname(. . . )innerhalb der Klasse • Der Begriff statisch (static) bezieht sich hierbei auf die Speicherallokation, die für statische Felder fix (statisch) zur Übersetzungszeit geschehen kann, statt dynamisch zur Laufzeit bei der Erschaffung eines Objekts • Ansonsten ist an static deklariertenVariablen nichtsstatisches • Die Werte von static Variablen können während der Laufzeit genauso variieren wie die jeder anderen Variable W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -17- Springer-Verlag, ISBN 3-540-20958-1
Klassenvariable und Klassenmethoden • Klassenmethoden heißen per Analogiestatic, da bei ihnen der Programmcode zur Übersetzungszeit (statisch) an den Methodennamen gebunden werden kann • Im Gegensatz zu Instanzmethoden, wo dies dynamisch zur Laufzeit geschieht • Siehe später • Klassenvariablen werden typischerweise für globaleBuchhaltungsaufgaben eingesetzt • Z. B. um in einer Klassenvariable die Anzahl aller erzeugten Klassenobjekte zu zählen. • Klassenmethoden ermöglichen auch eine alternativeAufrufsyntax, die für gewisse Operationen manchmal intuitiver ist • Durch Klassenmethoden haben wir „gewöhnliche“ Funktionen in Java simuliert W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -18- Springer-Verlag, ISBN 3-540-20958-1
Klassenvariable und Klassenmethoden • Bemerkung:In C++ gibt es nebenKlassenmethoden auch das Konzept der globalen Funktionen und globalen Variablen • Diese sind mit überhaupt keiner Klasse assoziiert • In Java gibt es dieses Konzeptnicht • Es kann aber dadurch simuliert werden, dass eine (öffentliche) Klasse (die z. B. Global heißen kann) eingeführt wird und dort alle globalen Variablen und Funktionen deklariert werden • Dies haben wir in verschiedenen Rahmenprogrammen ausgenutzt W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -19- Springer-Verlag, ISBN 3-540-20958-1
Pakete und Namensräume • In Java können Klassen zu Paketen(package) zusammengefasst werden • Um ein Paket PName zu vereinbaren, deklariert man package PName; vor den Klassendeklarationen • PName kann auch Punkte enthalten • Diese haben aber (zunächst) keine besondere Bedeutung • Sind jedoch idiomatischer Bestandteil von Paketnamen • Und spielen beim Ablegen von compilierten Klassen in eine Verzeichnisstruktur eine Rolle W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -20- Springer-Verlag, ISBN 3-540-20958-1
Pakete und Namensräume • Namen von Klassen sind in Java immer die „vollständig“ qualifizierten • Mit Paketname als Präfix • Beispiel: java.applet.Applet • Innerhalb des Pakets können sie aber ohne Paketname als Präfix aufgerufen werden • Außerhalb in der vollständig qualifizierten Form • Durch Pakete werden „Namensräume“ realisiert W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -21- Springer-Verlag, ISBN 3-540-20958-1
Pakete und Namensräume • Namensräume sind vor allem bei großenSoftwaresystemen wichtig • In denen mehrere Entwickler zusammenarbeiten • „Fremder“ (oder „alter“) Code integriert werden soll • Ohne Namensräume Gefahr groß, dass in einem anderen Programmteil der gleiche Name (für eine Klasse) schon gebraucht wurde • Konzept der Namensräume wurde daher inzwischen auch in C++ eingeführt W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -22- Springer-Verlag, ISBN 3-540-20958-1
Pakete und Namensräume • Eine Deklaration import PName.* macht die im Paket PName deklarierten Klassen von nun an auch ohne Verwendung des vollständig qualifizierten Namens bekannt • Diese können also in Kurzform aufgerufen werden, es muss also nicht der vollständig qualifizierte Namen verwendet werden • „Intern“ wird aber immer der vollständig qualifizierte Namen verwendet W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -23- Springer-Verlag, ISBN 3-540-20958-1
Pakete und Namensräume • Bemerkung: Als eine Besonderheit müssen die Klassen im Paket java.lang nicht explizit importiert werden, sondern diese werden schon implizit importiert • Vom Übersetzer wird also jeder Übersetzungseinheit automatisch eine Anweisung der Form import java.lang.*; vorangestellt W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -24- Springer-Verlag, ISBN 3-540-20958-1
Kapselung und Zugriffskontrolle • Jeder Name eines Mitglieds (Attribut oder Methode) einer Klasse hat einen Sichtbarkeitsbereich(scope) • Ein Mitgliedsname kann nur dort verwendet werden, wo er sichtbar ist • Zugriffe auf das Mitglied unterliegen damit einer Zugriffskontrolle(access control) • In Java gibt es die 4 Sichtbarkeitsbereicheglobal, geschützt, Paketund Klasse W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -25- Springer-Verlag, ISBN 3-540-20958-1
Kapselung und Zugriffskontrolle • Der Sichtbarkeitsbereich eines Mitglieds wird durch einen der folgenden Moderatoren(access modifiers) angegeben: • public(öffentlich, global), in UML: + • protected (geschützt), in UML: # • Zugriff von abgeleiteten Klassen aus • private (eigene Klasse), in UML: - • Ist nichts angegeben, gilt der Standard-Sichtbarkeitsbereich(default scope) „Paket“ W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -26- Springer-Verlag, ISBN 3-540-20958-1
Kontrakt und Aufrufschnittstelle • Beispiel: public class Date { // the class name is public private int day; // private field private int month; // private field private int year; // private field public void m1() { // public method // ... } void m2() { // package method // ... } private boolean m3() { // private method // ... } } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -27- Springer-Verlag, ISBN 3-540-20958-1
Kapselung und Zugriffskontrolle • Generell gilt in Java und in C++, dass der Zugriffsschutz auf Klassenebene stattfindet und nicht auf Objektebene • Eine Methode der Klasse A, die auf einem Objekt a1 abläuft, kann auf alle Attribute eines anderen Objekts a2 vom Typ A mit genau denselben Rechten zugreifen, als seien es ihre eigenen • Wir werden dies später ausnutzen, wenn die Additionsmethode der Klasse Complex die privatenFelder ihres Parameters vom Typ Complex liest W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -28- Springer-Verlag, ISBN 3-540-20958-1
Kontrakt und Aufrufschnittstelle • Die zugänglichen Daten und Methoden einer Klasse bilden die (Aufruf-)Schnittstelle(call interface) der Klasse nach außen • Auf dieser Sichtbarkeitsstufe (z. B. im Paket oder global) • Interne Daten und Methoden bleiben verborgen und können geändert werden, ohne dass extern davon etwas zu merken ist • Dies ist das wichtige Geheimnisprinzip(principle of information hiding) W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -29- Springer-Verlag, ISBN 3-540-20958-1
Kontrakt und Aufrufschnittstelle • Syntax und Semantik der Aufrufschnittstelle bilden den Kontrakt(contract) zwischen den Programmierern der Klasse und ihren Nutzern • Solange der Kontrakt beachtet wird, funktioniert die Zusammenarbeit zwischen den Nutzern der Klasse und dem Code der Klasse selbst • Die Art und Weise, wie die Klasse ihre Seite des Kontrakts erfüllt, ist unerheblich und kann wechselnden Erfordernissen angepasst werden • In bestimmten Fällen kann es nötig werden, weitere Zusicherungen in den Kontrakt aufzunehmen, z. B. Leistungsdaten • wie die asymptotische Komplexität von implementierten Algorithmen • oder garantierte Reaktionszeiten im Realzeitbereich W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -30- Springer-Verlag, ISBN 3-540-20958-1
Kontrakt und Aufrufschnittstelle • Es ist offensichtlich, dass der Kontrakt entsprechend sorgfältig dokumentiert werden muss • Hierzu gehören insbesondere die • Spezifikation der Methoden (Prozedurebene) • aber auch eine Beschreibung der Gesamtleistung der Klasse (Klassenebene) • Werkzeuge wie javadoc unterstützen sowohl die Spezifikation der Methoden wie auch die Beschreibung der Gesamtleistung der Klasse • Ein Dokumentationskommentar, der unmittelbar vor einer Klasse steht, wird von javadoc als Beschreibung der Gesamtleistung der Klasse interpretiert • Da private Felder und Methoden nicht zur Aufrufschnittstelle gehören, werden diese (und deren Dokumentation) von javadoc (in der Standardeinstellung) nicht mit in die erzeugte Dokumentation der Klasse aufgenommen W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -31- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher • In Java liegen Objekte grundsätzlich auf dem Haldenspeicher • Sie sind über Referenzvariable zugänglich, die auf dem Stapel liegen und deren Referenzen auf die Halde zeigen • Das Java-Laufzeitsystem (runtime system, runtime) organisiert die Halde mittels einer (halb-)automatischen Speicherverwaltung • Siehe später • Der Stapelspeicher wird ohnehin gemäß der Blockstruktur des Programms automatisch verwaltet • Der Operator new reserviert den benötigten Speicherplatz für ein Objekt der Klasse K durch die Anweisung new K(); • Außerdem wird Objekt initialisiert, siehe später W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -32- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher • Der Wert des Ausdrucks new K() ist eine Referenz auf das neu geschaffene Objekt • Mit K ref; deklariert man eine Referenzvariable für Objekte der Klasse K • Mit der Zuweisung ref = new K(); speichert man eine Referenz auf das neue anonyme Objekt in ref • Genau genommen ist ref jetzt ein Name für eine Referenz auf das Objekt • Da in Java aber Objekteimmernur über Referenzvariable zugänglich sind, sprechen wir manchmal salopp (by abuse of language) auch vom Objektrefstatt von der Objektvariablenref • In C++ lässt sich die Unterscheidung aber präzise treffen, da dort Objekte selbst Namen haben können W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -33- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher: Beispiel • Beispiel: Wir betrachten die Speicherbilder beim Ausführen folgender Codesequenz: { Time t; // Punkt 1 t = new Time(); // Punkt 2 } // Punkt 3 W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -34- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher: Beispiel (Forts.) { Time t; // Punkt 1 t = new Time(); // Punkt 2 } // Punkt 3 „Totes Objekt“ (siehe später) W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -35- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher: Erreichbarkeit • Objekte auf der Halde leben (unabhängig von der Blockstruktur des Programms) so lange, wie sie überReferenzvariable vom Stack aus erreichbar(reachable) sind • Direkt oder indirekt • Ein Objekt ist indirekt erreichbar, wenn es über eine Referenzvariable erreichbar ist, die als Feld in einem anderen erreichbaren Objekt vorkommt Das Objekt, das den Wert 0 enthält, ist direkt erreichbar, die weiteren Objekte sind indirekt erreichbar. W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -36- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher • Tote Objekte auf der Halde bezeichnet man als Abfall(garbage) • Um den Haldenspeicher wieder verwenden zu können, kennt das Java-Laufzeitsystem eine automatische Speicherbereinigungoder „Abfallsammlung“ (garbage collection) • Die es z.B. anstößt, wenn der Haldenspeicher zur Neige geht W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -37- Springer-Verlag, ISBN 3-540-20958-1
Explizite Verwaltung von Objekten im Speicher • In C++ hingegen muss (bzw. darf) die Speicherrückgabeexplizitprogrammiert werden • Der Programmierer muss für jede von ihm entworfene Klasse eine spezielle Funktion schreiben, einen sogenannten Destruktor(destructor), in der die Rückgabe des Speichers von einem nicht mehr benötigten Objekt beschrieben wird • Dieser ruft i.A. einen Operator delete auf • Dies ist in vielen Fälleneffizienter als eine automatische Speicherbereinigung • Ist aber für den Programmierer sehr viel umständlicher und kann leicht zu Programmierfehlern führen W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -38- Springer-Verlag, ISBN 3-540-20958-1
Insbesondere können dabei folgende Programmierfehler vorkommen Speicher für ein Objekt wird irrtümlicherweise nichtzurückgegeben, obwohl es tot ist Speicher für ein Objekt wird fälschlicherweise zurückgegeben wird, obwohl es noch nicht tot ist Explizte Verwaltung von Objekten im Speicher Immer mehr Speicher wird verbraucht „Speicherleck“ (memoryleak) Solche Fehler sind extrem boshaft, da sie erst dann bemerkt werden, wenn der Speicherplatz erneut zugeteilt und überschrieben wurde Können in C++ vorkommen, nicht in Java W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -39- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher: Garbage Collection • Ein einfaches Prinzip der automatischen Speicherbereinigung besteht aus zwei Phasen: • markieren(mark) und • (zusammen-)kehren(sweep) • In der Markierungsphase geht man von unten nach oben über den Stack und markiert rekursiv alle von den Referenzvariablen aus erreichbaren Objekte auf dem Heap • In der Kehrphase kehrt man allen nicht markierten Speicher auf dem Heap in eine Freispeicherliste(free list) zusammen und löscht die Markierungen • Man kann sogar die markierten Objekte in eine Ecke der Halde kehren (verschieben), denn der Java-Programmierer bekommt die tatsächlichen Werte der Referenzen nie zu Gesicht W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -40- Springer-Verlag, ISBN 3-540-20958-1
Verwaltung von Objekten im Speicher: Garbage Collection • Es gibt noch andere Prinzipien der Speicherbereinigung • Es ist in Javanichtfestgeschrieben, welche benutzt werden • Mit komplizierteren Methoden kann z. B. erreicht werden, dass Objekte, die oftmals in kurzen Abständen hintereinander benutzt werden (z. B. in einer Schleife), nach einer Speicherbereinigung in benachbarte Stellen im Speicher zu liegen kommen • Alle modernen Prozessoren sind mit einem Zwischenpeicher(Cache-Speicher, cache memory) ausgestattet, auf den sehr viel schneller als auf den Hauptspeicher zugegriffen werden kann • Dieser hat eine beschränkte Größe, es können aber zusammenhängende Stücke vom Hauptspeicher sehr schnell zu ihm transferiert werden • Somit kann evtl. die Ablaufgeschwindigkeit eines Programms erheblich gesteigert werden, wenn bei der Speicherbereinigung verkettete Objekte in benachbarte Bereiche im Heap gelegt werden • Weiteres mögliches Problem bei Garbage Collection: Echtzeitanwendungen W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -41- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren • Der Aufruf new K()reserviert nicht nur den benötigten Speicherplatz für ein neues Objekt der Klasse K, sondern er sorgt auch für eine Initialisierung • Als erstes werden die Instanzvariablen des Objekts je nach deren Typ mit Varianten von Null (0, 0d, 0f, \u0000, false oder null) belegt (vorinitialisiert) • Oftmals genügt die Initialisierung eines Objektes mit Null-Feldern nicht • sondern die Felder sollen andere Werte erhalten • evtl. auch noch dynamisch in Abhängigkeit von Ort und Zeit der Erschaffung • Zu diesem Zweck können in der Objekt-Klasse Konstruktoren(constructors) definiert werden W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -42- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren • Konstruktorenhaben Ähnlichkeit mit Methoden • Aber sie haben keinen Ergebnistyp (auch nicht den leeren Typ void) • Sie gelten nicht als Methoden • Alle Möglichkeiten der Zugriffskontrolle für Methoden gibtes auch für Konstruktoren • Jeder Konstruktor trägt den Namen seiner Klasse • Verschiedene Konstruktoren einer Klasse unterscheiden sich lediglich in der Anzahl bzw. dem Typ ihrer Parameter W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -43- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren • Als Seiteneffekt der Objekterzeugung mit new wird ein passender Konstruktoraufgerufen • nachdem new das neue Objekt mit (verschiedenen Arten von) Null vorinitialisiert hat • Die Anweisung new K(); ruft denjenigen Konstruktor von K auf, der keine Parameter hat (no-arg constructor) • Zum Beispiel ruft new K(5) den Konstruktor mit einem Parameter vom Typ int auf, usw. • Ein Konstruktor kann einen anderen in derselben Klasseexplizitaufrufen (explicit invocation) mit this(args) • Er kann einen Konstruktor der unmittelbaren Oberklasse mit super(args) aufrufen • Siehe später für Oberklassen und super • Ist in einer Klasse überhaupt kein Konstruktorprogrammiert, so ergänzt der Übersetzer einen no-arg Konstruktor als Standard-Konstruktor: • K(){ super(); } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -44- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren • Durch den Aufruf eines Konstruktors wird zuallererst der Konstruktor der unmittelbaren Oberklasse aufgerufen • Falls die erste Anweisung im Rumpf des Konstruktors nichtsuper(. . . ) ist, so wird automatischsuper() eingefügt • Danach werden alle Initialisierungsanweisungen ausgeführt, die in den Deklarationen der Instanzvariablen angegeben wurden • Wir bemerken hier, dass die Initialisierungen bisher (mit Ausnahme des Aufrufs des Konstruktors der Oberklasse) statischer Natur waren, da sie bereits zur Übersetzzeit für jedes Objekt fixiert waren • Nun beginnt der dynamische Teil der Initialisierung • In diesem können die Instanzvariablen durch den Code des Konstruktors auf Werte gesetzt werden, die von den Parametern des Konstruktoraufrufs abhängen oder sonst wie an dieser Stelle dynamisch berechnet werden können W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -45- Springer-Verlag, ISBN 3-540-20958-1
Wir definieren eine Datumsklasse Date mit 4 Konstruktoren der Stelligkeit 0 bis 3 Der nullstellige setzt das Datum auf den 1.1.0 Die anderen Konstruktoren der Stelligkeit rufen zunächst den (n-1)-stelligen Konstruktor explizit auf und überschreiben entweder das Jahr, den Monat und das Jahr, oder Tag, Monat, Jahr Initialisierung und Konstruktoren: Beispiel A public class Date { private byte day, month; private short year; // Konstruktoren public Date(){day= (byte)1; month= (byte)1;} public Date(short y) {this(); year=y; } public Date(byte m, short y){ this(y); month = m; } public Date(byte d, byte m, short y){ this(m,y); day=d; } // Selektoren public byte getDay() { return day; } public byte getMonth(){ return month; } public short getYear(){ return year; } public void setDay(byte d) { day=d;} public void setMonth(byte m) { month=m;} public void setYear(short y) { year=y;} // Darsteller public String toString() { return (day + "." + month + "." + year); } } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -46- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren: Beispiel A public class Date { private byte day, month; private short year; // Konstruktoren public Date(){day= (byte)1; month= (byte)1;} public Date(short y) {this(); year=y; } public Date(byte m, short y){ this(y); month = m; } public Date(byte d, byte m, short y){ this(m,y); day=d; } // Selektoren public byte getDay() { return day; } public byte getMonth(){ return month; } public short getYear(){ return year; } public void setDay(byte d) { day=d;} public void setMonth(byte m) { month=m;} public void setYear(short y) { year=y;} // Darsteller public String toString() { return (day + "." + month + "." + year); } } Nun sind folgende Definitionen von Variablen vom Typ Date möglich: Date aday = new Date(); // Das Datum 1.1.0 Date bday = new Date((short) 1970); // Das Datum 1.1.1970 Date cday = new Date((byte) 8, (short) 1975); // Das Datum 1.8.1975 Date dday = new Date((byte) 23, (byte) 8, (short) 2002); // Das Datum 23.8.2002 W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -47- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren: Beispiel B Eine Klasse Id soll so beschaffen sein, dass jedes Objekt eine persönliche Kennziffer (ID = identification) trägt, die es innerhalb der Klasse unverwechselbar macht Dazu hält sich Id eine Klassenvariable als Zähler, der ganz zu Beginn, bevor es noch Objekte gibt, ein einziges Mal zu 1 initialisiert wird Der Konstruktor weist seinem Objekt den Wert des Zählers als Kennziffer zu und inkrementiert danach den Zähler public class Id { static int counter = 1; private int id; public Id() { id = counter++;} int getId() {return id;} } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -48- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung und Konstruktoren • Bemerkung: • Konstruktoren besitzen zwar keineRückgabewerte, es ist aber möglich, dass in einem Konstruktor Ausnahmeobjekte geworfen werden, die dann wie bei anderen Methoden mit throws deklariert werden müssen • Siehe später W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -49- Springer-Verlag, ISBN 3-540-20958-1
Initialisierung von Klassenvariablen • Die Klassenvariablen (class variables, static variables) werden ein einzigesMalinitialisiert, wenn die Klasse zum ersten Mal aktiv gebraucht wird, aber noch bevor es Objekte gibt • Wiederum werden die Variablen mit (Varianten von) Null vorinitialisiert • Danach werden die Initialisierungsanweisungen ausgeführt, die im Zuge der Variablendeklarationen angegeben wurden • Beispiel: static int i=1; • Und es werden alle statischen Initialisierungsblöcke(static initializers) ausgeführt • Diese sind von der Art staticBlockund erlauben eine größere Freiheit in der Initialisierung, inklusive des Aufrufs von Klassenmethoden • Beispiel: static { i=f()+2; } W. Küchlin, A. Weber: Einführung in die Informatik – objektorientiert mit Java -50- Springer-Verlag, ISBN 3-540-20958-1