• Keine Ergebnisse gefunden

Info B VL 3: Klassen und ihre Komponenten

N/A
N/A
Protected

Academic year: 2021

Aktie "Info B VL 3: Klassen und ihre Komponenten"

Copied!
33
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Info B VL 3: Klassen und ihre Komponenten

Objektorientiere Programmierung in Java 2003

Ute Schmid (Vorlesung) Elmar Ludwig ( ¨ Ubung)

FB Mathematik/Informatik, Universit¨at Osnabr¨uck

Info B VL 3: Klassen und ihre Komponenten – p.50

(2)

Wdh: Komponenten von Klassen

Klassen können folgende Komponenten/Members enthalten

Felder

Methoden

(innere) Klassen (später)

Eine Komponente kann an die Klasse (static) oder an eine Instanz der Klasse gebunden sein.

Instanzmethoden können sich auf ihr aufrufendes

Objekt beziehen.

(3)

this (1)

a = c.area();

area() ist scheinbar parameterlos, aber die Methode hat einen impliziten Parameter this .

this hat als Wert die Referenz auf das Objekt, über das die Methode aufgerufen wurde.

this muss häufig nicht explizit angegeben werden:

Wenn eine Methode auf Komponenten zugreift, wird – wenn nichts anderes gesagt wird – angenommen, dass die Komponenten des aktuellen Objekts gemeint sind.

Info B VL 3: Klassen und ihre Komponenten – p.52

(4)

this (2)

this kann/sollte explizit angegeben werden, wenn man klar machen will, dass die Methode auf ihre eigenen Komponenten zugreift.

public double area(){

return Circle.PI * this.r * this.r; }

this wird explizit benötigt, wenn Parameter oder lokale Variablen einer Methode denselben Namen

haben wie Felder. Der Name wird zunächst auf lokale Grössen bezogen!

public void setRadius(double r) {

this.r = r; //Assign the argument r to the field this.r }

r = r ist sinnlos: weist Parameter r seinen eigenen Wert zu.

Klassen-Methoden können das this Schlüsselwort

(5)

Instanz- oder Klassenmethode?

Instanz-Methoden sind zentral für objekt-orientierten Programmierstil.

Dennoch kann es sinnvoll sein, Klassen-Methoden zu definieren.

Design-Entscheidung: Wenn häufig die Fläche eines Kreises berechnet werden soll, aber es ansonsten nicht notwendig ist, dafür extra ein Objekt der Klasse Circle zu erzeugen, sollte area() als

Klassen-Methode definiert werden.

Die Methode kann zweimal definiert sein (hier: einmal als Klassen-, einmal als Instanz-Methode).

Unterscheidung: verschiedene Signaturen!

public static double area(double r){

return PI * r * r;}

Info B VL 3: Klassen und ihre Komponenten – p.54

(6)

Beispiel bigger() (1)

Design-Entscheidung: Wie soll eine Methode realisiert werden, die den grösseren von zwei Kreisen

zurückliefert?

// Compare the implicit ‘this’ circle to the ‘that’ circle passed // explicitly as an argument and return the bigger one.

public Circle bigger(Circle that) { if(this.r > that.r) return this;

else return that;

} ...

Circle biggest = c.bigger(d); // Instance method:

// alternatively d.bigger(c)

(7)

Beispiel bigger() (2)

// Compare circle a to circle b and return // the one with the larger radius

public static Circle bigger(Circle a, Circle b) { if(a.r > b.r) return a;

else return b;

} ...

Circle biggest = Circle.bigger(x,y); // Static method

Info B VL 3: Klassen und ihre Komponenten – p.56

(8)

Referenztypen

Klassen (und Arrays) sind Referenztypen. Objekte haben einen bestimmten Typ:

Circle c = new Circle();

c ist ein Objekt vom Typ Circle int[] a =

1,2,3,4,5

;

a ist ein Array-Objekt String s = "Hello";

s ist ein String-Objekt

Array und String haben speziellen Status

(9)

Arrays/Strings

In der Object -Hierarchie findet sich keine Unterklasse Array

Es gibt potentiell unendlich viele Arrays

(Dimensionalität, Typ der Elemente). Wie bei der

Definition und Erzeugung anderer Objekte steht links der Typ des Arrays (Dimensionalität und Typ der

Elemente), aber nicht die Länge des Arrays! (siehe Vorlesung Informatik A)

int[] queens = new int[8];

default-mäßig mit 0en initialisiert

Für String kann ein Objekt direkt initialisiert werden:

Text vom Typ String (Zeichen in doppelten

Anführungszeichen) kann direkt an eine Variable vom Typ String zugewiesen werden.

String s = "This is an" +

"error message"; Info B VL 3: Klassen und ihre Komponenten – p.58

(10)

Referenzen (1)

Primitive Datentypen: feste, bei Deklaration bekannte Grösse (z. B. int bekommt 32 Bit)

Klassen und Arrays: zusammengesetzte Typen (composite types)

keine Standardgrösse angebbar

benötigen häufig mehr Speicherplatz

Manipulation by reference (aber: call by value

Parameterübergabe-Mechanismus!)

null Referenz: Referenz auf “Nichts”, Abwesenheit

einer Referenz; Wert null kann an jede Variable für

einen Referenztyp zugewiesen werden

(11)

Referenzen (2)

Referenz: fester Wert (Speicheradresse), der auf das Objekt verweist

Zuweisung eines Objekts an eine Variable: Variable hält Referenz auf dieses Objekt

Übergabe eines Objekts als Parameter: Methode erhält die Referenz, über die das Objekt manipuliert werden kann

Java erlaubt keine explizite Manipulation von Referenzen

Wichtiger Unterschied zwischen primitiven Datentypen und Referenztypen: Kopieren von Werten und Prüfung von Gleichheit

Info B VL 3: Klassen und ihre Komponenten – p.60

(12)

Kopieren von Werten vs. Referenzen

int x = 42;

int y = x;

Circle c = new Circle();

c.r = 2.0;

Circle d = c;

c d

2411 2412

4711 4711

4711 x

y

1124 1125

42 42

Object

r=2.0

(13)

Kopieren von Objekten (und Arrays)

Für die int-Variablen x und y existieren zwei Kopien des 32-bit Integers 42.

Variable d enthält eine Kopie der Referenz, die in Variable c steht. Man spricht hier auch von aliasing.

Achtung: Wenn zwei Referenzen a und b auf dasselbe Objekt zeigen, kann ein Methodenaufruf (z.B a.f() ) an das eine Objekt den Wert eines Feldes ändern

(“calling a method for its side effects”). Das Feld ist

dann beim Objekt geändert. Sowohl a.feld als auch b.feld liefern den aktuellen Wert!

Eine Kopie des Circle Objekts in der Java VM, aber zwei Kopien der Referenz auf dieses Objekt!

Info B VL 3: Klassen und ihre Komponenten – p.62

(14)

Beispiel ‘Circle’

Circle c = new Circle();

c.r = 2.0;

Circle d = c; // c and d refer to same object System.out.println(c.r); // Print out radius of c: 2.0 d.r = 4.0; // Change radius of d

System.out.println(c.r); // Print out radius of

// c again: 4.0

(15)

Clonen

Kopieren des Objektes selbst: clone()

Objekte müssen zu einer Klasse gehören, die als Cloneable deklariert ist (Implementieren des

Cloneable -Interfaces und der clone() -Methode) Arrays sind immer Cloneable

clone() erzeugt eine flache (“shallow”) Kopie: alle primitiven Werte und Referenzen werden kopiert. Das heisst, Referenzen werden nicht ge-cloned!

rekursives Kopieren muss explizit implementiert werden.

Casting ist notwendig: clone() liefert Object

Info B VL 3: Klassen und ihre Komponenten – p.64

(16)

Clonen von Arrays

int[] data = {1,2,3,4,5}; // An array

int[] copy = (int[]) data.clone(); // A copy of the array int[][] data = {{1,2,3},{4,5}}; // Array of 2 refs

int[][] copy = (int[][]) data.clone(); // Copy copy[1] = new int[]{7,8,9};

// this does not change data[1]

copy[0][0] = 99; // this changes data[0][0] too!

int[][] data = {{1,2,3},{4,5}}; // Array of 2 refs int[][] copy = new int[data.length][]; // new array

// to hold copied arrays

for (int i = 0; i < data.length; i++)

(17)

Illustration

1 2 3

1 2 3

4 5

4 5

data copy

7 8 9

0 1

0 1

data copy

int[][] copy = (int[][]) data.clone();

copy[1] = new int[] {7,8,9};

copy[0][]0]

Info B VL 3: Klassen und ihre Komponenten – p.66

(18)

Clonen von Objekten

Clonable Objekte müssen das (Marker) Interface Cloneable implementieren

und die in Object definierte clone() Methode überschreiben

(Vorgriff auf spätere Kapitel)

CloneCircle e = new CloneCircle();

e.r = 3.0;

CloneCircle f = (CloneCircle) e.clone(); // copy object

System.out.println("Do circles e and f have the same reference? ");

if (e == f)

System.out.println("yes");

else System.out.println("no"); // no, they do not!

f.r = 5.0; // only changes r in f

System.out.println(e.r); // still 3.0

(19)

Gleichheit von Objekten (und Arrays)

== Operator bei primitiven Typen: Prüfung auf selben Wert (bei ganzzahligen Werten: gleiche Bits)

== Operator bei Referenztypen: Prüfung, ob zwei Referenzen auf dasselbe Objekt verweisen,

aber nicht, ob zwei Objekte denselben Inhalt haben!

Prüfung der Gleichheit von Inhalten von Objekten:

equals()

Methode ist in Object definiert (default ist == )

Methode in eigener Klasse entsprechend überschreiben (z.B. in String gemacht)

Anmerkung: zur Unterscheidung “equals” für Gleichheit von Referenzen und “equivalent” für

Gleichheit von Inhalten verschiedener Objekte. Die Benennung der Methode equals ist etwas ungünstig

Info B VL 3: Klassen und ihre Komponenten – p.68

(20)

Beispiel ‘Circle’

// A class method for Circle replacing the // instance method equals() in Object

public static boolean equals (Circle c, Circle d) { return c.r == d.r;

}

Circle c = Circle();

c.r = 2.0;

Circle d = Circle();

d.r = 2.0;

if (c == d) System.out.println("equal");

// but c and d are not equal if (Circle.equals(c,d))

System.out.println("equivalent");

(21)

Wrapper-Klassen

Problem: Array ist ein Container für primitive Typen wie beliebige Objekte. Manchmal möchte man primitive

Typen vielleicht in anderen Datenstrukturen speichern ( Vector aus den Java Collection Classes in

java.util ). Diese Klassen sind für Object definiert, aber nicht für primitive Typen.

Lösung: Einpacken von primitiven Typen in

korrespondierende Klassen (Wrapper) – Boolean, Byte, Short, Integer, Long, Character, Float, Double Dort werden Konstanten und nützliche (statische) Methoden definiert.

Info B VL 3: Klassen und ihre Komponenten – p.70

(22)

Beispiel Wrapper

// java.lang.Integer

public Integer(String s) throws NumberFormatException;

public Integer(int value);

public static int parseInt(String s)

throws NumberFormatException;

public int compareTo(Integer anotherInteger);

String s = "-42";

int i = Integer.parseInt(s); // class method

Integer j = new Integer(-50); // create new Integer Object int t = j.compareTo(new Integer(i)); // instance method

// >0 if j>i, <0 if j<i, 0 if j=i

(23)

Pakete und Namensräume

Paket: Organisation von Klassen; Konzept, um eindeutige Klassennnamen zu garantieren

Namespace: Menge von einzigartigen Namen.

Organisation von Klassen in Pakete wird vor allem beim Erstellen grösserer Programme interessant (Strukturierung und Kapslung)

Die von Java zur Verfügung gestellten Klassen sind in Paketen organisiert.

zur Nutzung der APIs ist

grundlegendes Verständnis von Paketen und Namensräumen nötig

Sichtbarkeitsmodifikatoren sind mit dem Paket-Konzept von Java verknüpft (später)

Info B VL 3: Klassen und ihre Komponenten – p.72

(24)

Import

Java API, z.B. /usr/lib/jdk1.3/jre/lib/rt.jar

Auf alle (zugreifbaren) Komponenten von Klassen kann mit dem voll-qualifizierten Klassennamen

zugegriffen werden.

System.out.println("Hello World!");

Durch eine import Anweisung kann mit dem einfachen Klassennamen zugegriffen werden.

z.B. import java.io.*; : alle Klassen des

I/O-Pakets, import java.io.InputStream; : Klasse InputStream des I/O-Pakets.

Warnung: undifferenzierter Import mit .* birgt die Gefahr von ungewollten Kollisionen!

java.lang (core API) wird automatisch importiert.

(25)

Klasse ‘System’

System.out.println("Hello World!");

System ist eine Klasse (genauer java.lang.System ).

out ist ein Klassen-Feld von System (vom Typ java.io.Printstream ).

System.out verweist auf ein Objekt.

Das Objekt hat eine Instanz-Methode println() .

Info B VL 3: Klassen und ihre Komponenten – p.74

(26)

Ausschnitt aus ‘rt.jar’

0 Wed Oct 25 05:30:36 CEST 2000 java/lang/

1428 Wed Oct 25 05:30:34 CEST 2000 java/lang/Object.class 11661 Wed Oct 25 05:30:34 CEST 2000 java/lang/String.class

155 Wed Oct 25 05:30:34 CEST 2000 java/lang/Comparable.class 7193 Wed Oct 25 05:30:34 CEST 2000 java/lang/Class.class

325 Wed Oct 25 05:30:34 CEST 2000 java/lang/CloneNotSupportedException.class 291 Wed Oct 25 05:30:34 CEST 2000 java/lang/Exception.class

1559 Wed Oct 25 05:30:34 CEST 2000 java/lang/Throwable.class ...

113 Wed Oct 25 05:30:36 CEST 2000 java/io/Serializable.class 293 Wed Oct 25 05:30:36 CEST 2000 java/io/IOException.class

4064 Wed Oct 25 05:30:36 CEST 2000 java/io/ObjectStreamField.class

...

(27)

Pakete in Java (1)

Jede Klasse hat einen einfachen Namen, z.B. Circle oder InputStream , sowie einen voll-qualifizierten

Namen, z.B. java.io.InputStream .

Indem man als erstes die Anweisung package

name

; in einer Datei schreibt, bestimmt man, dass alle Klassen in dieser Datei zum Paket name

gehören.

Beispielsweise gehört die Klasse InputStream zum Paket java.io .

Eine Datei, in der eine Klasse definiert wird, kann also vor der Klassendefinition noch eine Paket-Definition (als aller erstes, ausser Kommentar) sowie beliebig viele Import-Anweisungen enthalten.

Info B VL 3: Klassen und ihre Komponenten – p.76

(28)

Pakete in Java (2)

package mypackage;

import java.io.InputStream;

import java.util.Stack;

public class MyClass { // definition

}

(29)

Pakete in Java (3)

Gibt man für eine Datei keine Paket-Anweisung an, so gehören alle dort definierten Klassen zu einem default (unbenannten) Paket.

Im Allgemeinen bestehen Pakete aus mehreren Klassen.

Die Klassen eines Pakets stehen in einem gemeinsamen Verzeichnis.

Das Verzeichnis muss denselben Namen wie das Paket haben.

Vorteile:

Mehr Übersicht und Ordnung in den Dateien.

Einzigartige, voll-qualifizierte Klassennamen!

Java-Konvention: Der erste Teil des Paket-Namens ist der umgedrehte Internet-Domain-Name des

Nutzers, der die Klasse erzeugt.

Info B VL 3: Klassen und ihre Komponenten – p.78

(30)

Pakete in Java (4)

Wenn ein Java-Programm läuft und eine Klasse

( *.class ) geladen werden soll (dynamic loading), wird der Paket-Name in einen Verzeichnisnamen (Pfad) aufgelöst.

Um die entsprechenden absoluten Pfade zu finden,

schaut der Java-Interpreter in der Variable CLASSPATH nach und beginnt in den dort gegebenen

Verzeichnissen mit der Suche.

Diese Variable wird üblicherweise über das Betriebssystem gesetzt.

Es ist nützlich, eigene Makefile s zu schreiben, in denen die konkret benötigten Klassenpfade

angegeben sind (Übung!)

(31)

Namenskollisionen

Was passiert, wenn zwei Pakete importiert werden, die Klassen mit demselben Namen enthalten?

import java.util.*; // enthaelt Vector import mycollection.*; // enthaelt Vector

Zunächst: nur potentielle Kollision.

Der Compiler beschwert sich nicht, solange die Klasse Vektor nicht genutzt wird.

Erst wenn versucht wird, ein Objekt der Klasse Vector zu erzeugen, meldet der Compiler das Problem.

Lösung: java.util.Vector v = new

java.util.Vector(); kennzeichnet eindeutig, welche Klasse gemeint ist.

Anmerkung: Der Compiler ersetzt alle Klassennamen durch ihre voll-qualifizierten Namen.

Info B VL 3: Klassen und ihre Komponenten – p.80

(32)

Verhaltensänderungen

Achtung: Wenn via import Klassen genutzt werden, so kann das eigene Programm sein Verhalten

verändern, wenn die Definitionen einer importierten Klasse geändert wurden.

Wenn die importierten Klassen nicht selbstgeschrieben sind, kann dies, wenn es dumm läuft, unbeabsichtigt sein und zu Fehlern in der eigenen Klasse führen!

Guter Stil ist es, dass solche Klassen und

Komponenten, die öffentlich zur Verfügung gestellt werden, eine klar definierte und dokumentierte

Schnittstelle (Art und Anzahl der Parameter, Rückgabewert) haben und dass die

Funktionalität/Semantik der öffentlich zur Verfügung

gestellten Klassen nicht (bzw. nicht ohne alle Nutzer zu

(33)

Verfolgen des Ladens von Klassen

Verfolgen, welche Klassen für ein Programm geladen werden mit

java -verbose CircleTest

$ java -verbose CircleTest

[Opened /usr/lib/jdk1.3.1/jre/lib/rt.jar]

[Loaded java.lang.Object from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

[Loaded java.io.Serializable from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

[Loaded java.lang.Comparable from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

[Loaded java.lang.String from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

[Loaded java.lang.Class from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

...

[Loaded CircleTest]

[Loaded Circle]

[Loaded java.lang.FloatingDecimal from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

[Loaded java.lang.Math from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

Circle c Radius: 2.0 ...

[Loaded java.lang.Shutdown$Lock from /usr/lib/jdk1.3.1/jre/lib/rt.jar]

Info B VL 3: Klassen und ihre Komponenten – p.82

Referenzen

ÄHNLICHE DOKUMENTE

MouseListener MouseAdapter mouseEntered, mousePressed, mouseReleased, mouseClicked, mouseExited MouseMotionListener MouseMotionAdapter mouseDragged, mouseMoved. MouseWheelListener

Schlüssel minimale Menge von Attributen, deren Werte ein Tupel einer Ta- belle eindeutig identifizieren Primärschlüssel ein beim Datenbankentwurf aus-.

• Weil Objekt-Methoden nur für von null verschiedene Objekte aufgerufen werden können, kann die leere Liste nicht mittels. toString() als String

Erstellen Sie hierzu die Klasse DiGraph als Hauptklasse f¨ ur den Graphen, sowie die Klassen Node und Edge, f¨ ur die Knoten und Kanten.. Da ein Graph aus einer beliebigen Anzahl

➥ Uber Methode ¨ java.beans.Introspector.getBeanInfo() kann Information ¨uber eine Bean abgefragt werden:. ➥ Methoden, Properties,

Instanzdaten können durch eine gewöhnliche Initialisie- rung, durch einen Konstruktor oder einen Initialisierer initialisiert werden. Instanzdaten werden automatisch mit

Beim Beenden des Servers getServletInfo Liefert Info zu Servlet. Methoden

tor drei Operanden: eine Bedingung und zwei Aus- drücke, von denen je nach Ergebnis der Bedingung einer ausgeführt wird.. switch-Verzweigung Diese dient dazu, den Wert einer