Programmieren I Kapitel 10. Spezielle Features Martin Griebl Universität Passau Kapitel 10: Spezielle Features Ziel: Besonderheiten von Java bei OO­Konzepten ■ statische Attribute und Methoden ■ innere, verschachtelte und lokale Klassen ■ anonyme Klassen ■ Enumerationstypen ■ Methoden höherer Ordnung: ■ Methoden als Parameter von Methoden ■ Methoden als Resultate von Methoden Martin Griebl Universität Passau Von objektorientiert zu imperativ mit „static“ ■ Definition: statische Attribute (auch: Klassenvariable): für alle Objekte der Klasse nur einmal vorhanden ■ ansprechbar: auch über <<Klassenname>>.<<Attributname>> ■ Beispiele und Anwendungen: ■ Name der log­Datei (Protokolldatei), in die alle Objekte ihre Aktivitäten protokollieren ■ Buchführungsfunktionen einer Klasse über all ihre Instanzen (=Objekte) ■ Klassenweite Konstanten static final float GRAVITY=9.81F; Martin Griebl Universität Passau Konkretes Beispiel (1/2) ■ schöne Druckausgabe von Strings in gleich großen Käst­chen; Kästchenbreite richtet sich nach längstem String ■ Kästchenbreite ist für alle gleich => statisches Attribut ■ class BoxedString { static int width; String name; } ■ BoxedString bs1 = new BoxedString(); BoxedString bs2 = new BoxedString(); bs1.name = “Ein Text“; bs2.name = “Dies ist noch ein Text“; bs2.width = max(wd(bs1.name), wd(bs2.name)); Martin Griebl Universität Passau Einsatz statischer Attribute ■ Im Beispiel gilt: bs2.width = bs1.width = BoxedString.width ■ Grund: ein statisches Attribut gibt es nur einmal im Speicher ■ Also Vorsicht vor den Seiteneffekten (bs2 modifiziert scheinbar bs1) ■ Folge: gute Benutzung von statischen Variablen nicht über Objektnamen wie bs2.width oder bs1.width, sondern über den Klassennamen, also BoxedString.width ■ Für bestimmte Aufgaben sinnvoll, aber keinesfalls zum Einsparen von lokalen Variablen oder Parametern von Methoden verwenden!! Martin Griebl Universität Passau Konkretes Beispiel (2/2) ■ bessere Lösung: class BoxedString { static int width; String name; BoxedString(String name) { this.name = name; width = Math.max(wd(name)); } ■ BoxedString bs1 = new BoxedString(“Ein Text“); BoxedString bs2 = new BoxedString (“Dies ist noch ein Text“); // BoxedString.width ist automatisch korrekt Martin Griebl Universität Passau Statische Methoden ■ Definition: eine statische Methode gehört zur Klasse, nicht zu einzelnen Objekten ■ kann daher nur auf statische Attribute zugreifen und statische Methoden aufrufen ■ Beispiel: public static void main (...) ... ■ ■ Nicht jedes Objekt hat sein main, sondern die Klasse einmal. In main werden erst Objekte kreiert. Zweck: Notationsvereinfachung für Utility­Klassen wie Math, System,..., denn erst ein Math­Objekt erzeugen zu müssen, um dann dessen .sin(1.3) aufzurufen, wäre sinnlos. Stattdessen: Math.sin(1.3) Martin Griebl Universität Passau Initialisierung von Variablen ■ statische Attribute werden beim Laden der Klasse initialisiert (ggf. mit einem Standardwert) ■ normale Attribute werden beim Kreieren des Objekts initialisiert (ggf. mit einem Standardwert) ■ Lokale Variablen werden bei der ersten Wertzuweisung initialisiert (sofern es sie gibt, d.h.: keine Standardinitialisierung) Martin Griebl Universität Passau Spezielle Arten von Klassen Die im Folgenden vorgestellten Klassen sind hier nur der Vollständigkeit halber erwähnt; den Sinn Innerer Klassen werden wir nach der Diskussion von Sichtbarkeiten verstehen. ■ Martin Griebl ■ Innere Klassen ■ Verschachtelte Klassen ■ Lokale Klassen ■ Anonyme Klassen Universität Passau Innere und verschachtelte Klassen ■ Definition: eine Klasse, die innerhalb einer anderen Klasse deklariert wird und nicht als static deklariert ist, ist eine (echte) innere Klasse ■ innerhalb, aber static => verschachtelte Klasse ■ (Echte) innere Klassen erlauben keine static Attribute, verschachtelte Klassen schon ■ verschachtelte Klassen sind wie „normale äußere“ Klassen ■ Objekte innerer Klassen gehören zu einem „äußeren Objekt“ und können, nachdem dieses sie erzeugt hat, auf dessen Attribute und Methoden zugreifen. Martin Griebl Universität Passau Innere Klassen (Künstliches) Beispiel: class Outer { int a=42; int foo(int x) { return 2*x; } ■ class Inner { int i = foo(a); void bar() { this.i = Outer.this.a; } } } ■ analoge Notation zu this für new und super, z.B: Outer o = new Outer(); Outer.Inner i = o.new Inner(); Martin Griebl Universität Passau Lokale Klassen ■ Definition: innerhalb einer Methode oder eines Blocks definierte Klasse ■ static ist sinnlos; nur im Block sichtbar ■ können nicht auf die Variablen (sondern nur finals) der Methode zugreifen Martin Griebl Universität Passau Anonyme Klassen ■ Definition: lokale Klassen ohne Namen ■ damit ohne Konstruktor => Erweiterung von new um Argumente und Klassenrumpf ■ Beispiel: Minimalstklassen im Zusammenhang mit GUIs (nicht Thema der Vorlesung) Martin Griebl Universität Passau Anonyme Klassen ■ Beispiel au dem GUI­Bereich: void foo() { class Mylistener extends MouseAdapter { public void mouseClicked(...) {doSomething();} } window.addMouseListener(new Mylistener()); ... } wird zu void foo() { window.addMouseListener(new MouseAdapter(){ public void mouseClicked(...) {doSomething();} } ); ... } Martin Griebl Universität Passau Enumerationstypen in Java ■ Enumerationstypen sind endliche Datentypen, deren mögliche Werte aufgezählt werden. ■ Beispiel: Ampelfarben sind rot, gelb, gruen ■ Hacker­Alternative: rot ≙ 0, gelb ≙ 1, gruen ≙ 2 ■ anständiger Hacker: public static final int rot=0; ... ■ Immer noch keine Typsicherheit! ■ Elegante Lösung seit Java 1.5: enum Ampelfarbe {rot, gelb, gruen}; Martin Griebl Universität Passau Enumerationstypen in Java Erweiterungen: ■ Martin Griebl ■ Argumente in () erlauben, eine allgemeine Konstruktorfunktion zu schreiben – mit Attributen Beispiel: enum Coin { penny(1), nickel(5), dime(10), quater(25); private final int val; Coin(int value) { val=value; } public int value() { return val;} } Und beim Aufrufer: Coin c = nickel; int v = c.value(); ■ Methoden in {} erlauben, individuelle Methodendefinitionen für jeden Wert zu schreiben Universität Passau Allgemeinere for­Schleifen ab Java 1.5 ■ bisher nur: for (int i=0; i<100; i++) {...} ■ Wunsch: ähnliches, komfortables for für Enumerationstypen ■ Lösung: die „for­in“­Schleife for (Ampelfarbe farb : Ampelfarbe.values()) { System.out.println(farb); } ■ values() ist geschenkt; (implizites) toString() auch ■ Dasselbe funktioniert für Iteratoren (später in der Vorlesung) und auch für Arrays: int [] a = {1,17,4,42}; for (int i : a ) { ... } Martin Griebl Universität Passau Warnung ■ Vorsicht: das Weiterlesen könnte dazu führen, dass Sie nicht mehr Java programmieren wollen ■ Wenn sich dieser Zustand einstellen sollte: überspringen Sie den Teil lieber. Er ist nur der Vollständigkeit halber angegeben und zeigt den trickreichen Einsatz von Interfaces und anonymen Klassen. Martin Griebl Universität Passau Methoden als Argumente ■ Methoden als Parameter (z.B. Sortierung oder für eine Differenzier­ Funktion diff die zu differenzierende Funktion f) ■ Erste Lösung: double diff(Fun f, double x) {...} interface Fun { double apply(double x) ; } class MyExpoFun implements Fun { public double apply(double x) { return Math.exp(2*x*x)/(x+1); } double d = diff( new MyExpoFun(), 0 ); Martin Griebl Universität Passau Methoden als Argumente ■ Anonyme Klassen vermeiden die Namenssuche ■ Lösung: double diff(Fun f, double x) {...} interface Fun { double apply(double x) ; } double d = diff( new Fun() { public double apply(double x) { return Math.exp(2*x*x)/(x+1); }, }, 0 ); ■ Meinungen? Martin Griebl Universität Passau Methoden als Argumente ■ Etwas schönere Lösung (doch mit einem Namen, aber ohne Klasse, also in dem Sinne immer noch eine anonyme Klasse): double diff(Fun f, double x) {...} interface Fun { double apply(double x) ; } Fun g = new Fun() { public double apply(double x) { return Math.exp(2*x*x)/(x+1); } }; double d = diff( g,0 ); Martin Griebl Universität Passau Methoden als Rückgabewerte ■ Beispiel: g = shift (f,delta), also g(x) = f(x­delta) ■ Lösung: Fun shift (final Fun f, final double delta) { return new Fun() { public double apply(double x) { return f.apply(x­delta); } }; } Martin Griebl Universität Passau Methoden als Rückgabewerte ■ Anwendungsbeispiel: cos = shift (sin,­/2) ■ Anwendung: Fun myCos = shift(mySin, ­Math.PI/2); ■ mit der zusätzlichen Definition Fun mySin = new Fun () { public double apply(double x) { return Math.sin(x); } }; ■ Meinungen? Martin Griebl Universität Passau Zusammenfassung ■ Statische Attribute und Methoden verhindern unnötiges Kreieren einer einzigen Laufzeitinstanz ■ Klassen kann man schachteln ■ Es gibt namenlose Klassen ■ Enumerationstypen und erweiterte for­Schleifen sind schöne Erweiterungen in Java 1.5 ■ Methoden höherer Ordnung sind krückenhaft implementierbar Martin Griebl Universität Passau