Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.
 
Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Objektorientierte Beziehungsfragen
7 Ausnahmen müssen sein
8 Äußere.innere Klassen
9 Besondere Typen der Java SE
10 Generics<T>
11 Lambda-Ausdrücke und funktionale Programmierung
12 Architektur, Design und angewandte Objektorientierung
13 Die Klassenbibliothek
14 Einführung in die nebenläufige Programmierung
15 Einführung in Datenstrukturen und Algorithmen
16 Einführung in grafische Oberflächen
17 Einführung in Dateien und Datenströme
18 Einführung ins Datenbankmanagement mit JDBC
19 Einführung in <XML>
20 Testen mit JUnit
21 Bits und Bytes und Mathematisches
22 Die Werkzeuge des JDK
A Java SE Paketübersicht
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 20,0 MB
- Übungsaufgaben, ca. 1,8 MB
- Musterlösungen, ca. 0,8 MB

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenbloom
Das umfassende Handbuch
Buch: Java ist auch eine Insel

Java ist auch eine Insel
Rheinwerk Computing
1306 Seiten, gebunden, 11. Auflage
49,90 Euro, ISBN 978-3-8362-2873-2
Pfeil 11 Lambda-Ausdrücke und funktionale Programmierung
Pfeil 11.1 Code = Daten
Pfeil 11.2 Funktionale Schnittstellen und Lambda-Ausdrücke im Detail
Pfeil 11.2.1 Funktionale Schnittstellen
Pfeil 11.2.2 Typ eines Lambda-Ausdrucks ergibt sich durch Zieltyp
Pfeil 11.2.3 Annotation @FunctionalInterface
Pfeil 11.2.4 Syntax für Lambda-Ausdrücke
Pfeil 11.2.5 Die Umgebung der Lambda-Ausdrücke und Variablenzugriffe
Pfeil 11.2.6 Ausnahmen in Lambda-Ausdrücken
Pfeil 11.2.7 Klassen mit einer abstrakten Methode als funktionale Schnittstelle? *
Pfeil 11.3 Methoden-Referenz
Pfeil 11.3.1 Varianten von Methoden-Referenzen
Pfeil 11.4 Konstruktor-Referenz
Pfeil 11.4.1 Standard- und parametrisierte Konstruktoren
Pfeil 11.4.2 Nützliche vordefinierte Schnittstellen für Konstruktor-Referenzen
Pfeil 11.5 Implementierung von Lambda-Ausdrücken *
Pfeil 11.6 Funktionale Programmierung mit Java
Pfeil 11.6.1 Programmierparadigmen: imperativ oder deklarativ
Pfeil 11.6.2 Funktionale Programmierung und funktionale Programmiersprachen
Pfeil 11.6.3 Funktionale Programmierung in Java am Beispiel vom Comparator
Pfeil 11.6.4 Lambda-Ausdrücke als Funktionen sehen
Pfeil 11.7 Funktionale Schnittstelle aus dem java.util.function-Paket
Pfeil 11.7.1 Blöcke mit Code und die funktionale Schnittstelle java.util.function.Consumer
Pfeil 11.7.2 Supplier
Pfeil 11.7.3 Prädikate und java.util.function.Predicate
Pfeil 11.7.4 Funktionen und die allgemeine funktionale Schnittstelle java.util.function.Function
Pfeil 11.7.5 Ein bisschen Bi …
Pfeil 11.7.6 Funktionale Schnittstellen mit Primitiven
Pfeil 11.8 Optional ist keine Nullnummer
Pfeil 11.8.1 Optional-Typ
Pfeil 11.8.2 Primitive optionale Typen
Pfeil 11.8.3 Erstmal funktional mit Optional
Pfeil 11.9 Was ist jetzt so funktional?
Pfeil 11.10 Zum Weiterlesen
 
Zum Seitenanfang

11.3Methoden-Referenz Zur vorigen ÜberschriftZur nächsten Überschrift

Je größer Softwaresysteme werden, desto wichtiger werden Dinge wie Klarheit, Wiederverwendbarkeit und Dokumentation. Wir haben für unseren String-Comparator eine Implementierung geschrieben, anfangs über eine innere Klasse, später über einen Lambda-Ausdruck. In jedem Fall haben wir Code geschrieben. Doch was wäre, wenn eine Utility-Klasse schon eine Implementierung mitbringen würde? Dann könnte der Lambda-Ausdruck natürlich an die vorhandene Implementierung delegieren, und wir sparen Code. Schauen wir uns das mal an einem Beispiel an:

class StringUtils {
public static int compareTrimmed( String s1, String s2 ) {
return s1.trim().compareTo( s2.trim() );
}
}
public class CompareIgnoreCase {
public static void main( String[] args ) {
String[] words = { "A", "B", "a" };
Arrays.sort( words, (String s1, String s2) -> StringUtils.compareTrimmed(s1, s2) );
System.out.println( Arrays.toString( words ) );
}
}

Auffällig ist hier, dass die referenzierte Methode compareTrimmed(String,String) von den Parametertypen und vom Rückgabetyp genau auf die compare(…)-Methode eines Comparator passt. Für genau solche Fälle gibt es eine weitere syntaktische Verkürzung, sodass im Code kein Lambda-Ausdruck, sondern nur noch ein Methodenverweis notwendig ist.

Definition

Eine Methoden-Referenz ist ein Verweis auf eine Methode, ohne diese jedoch aufzurufen. Syntaktisch trennen zwei Doppelpunkte den Klassenamen bzw. die Referenz auf der linken Seite von dem Methodennamen auf der rechten.

Die Zeile

Arrays.sort( words, (String s1, String s2) -> StringUtils.compareTrimmed(s1, s2) );

lässt sich mit einer Methoden-Referenz abkürzen zu:

Arrays.sort( words, StringUtils::compareTrimmed );

Die Sortiermethode erwartet vom Comparator eine Methode, die zwei Strings annimmt und eine Ganzzahl zurückgibt. Der Name der Klasse und der Name der Methode sind unerheblich, weshalb an dieser Stelle eine Methoden-Referenz eingesetzt werden kann.

Eine Methoden-Referenz ist wie ein Lambda-Ausdruck ein Exemplar einer funktionalen Schnittstelle, jedoch für eine existierende Methode einer bekannten Klasse. Wie üblich bestimmt der Kontext, von welchem Typ genau der Ausdruck ist.

[+]Hinweis

Gleicher Code für eine Methoden-Referenz kann zu komplett unterschiedlichen Typen führen – der Kontext macht den Unterschied:

Comparator<String> c1 = StringUtils::compareTrimmed;
BiFunction<String, String, Integer> c2 = StringUtils::compareTrimmed;
 
Zum Seitenanfang

11.3.1Varianten von Methoden-Referenzen Zur vorigen ÜberschriftZur nächsten Überschrift

Im Beispiel ist die Methode compareTrimmed(…) statisch, und links vom Doppelpunkt steht der Name eines Typs. Allerdings kann beim Einsatz eines Typnamens die Methode auch nichtstatisch sein, String::length ist so ein Beispiel. Das wäre eine Funktion, die ein String auf ein int abbildet, in Code:

Function<String, Integer> len = String::length;

Links von den zwei Doppelpunkten kann auch eine Referenz stehen, was dann immer eine Objektmethode referenziert.

[zB]Beispiel

Während String::length eine Funktion ist, wäre string::length ein Supplier, unter der Annahme, dass string eine Referenzvariable ist:

String string = "Goll";
Supplier<Integer> len = string::length;
System.out.println( len.get() ); // 4

System.out ist eine Referenz, und eine Methode wie println(…) kann an einen Consumer gebunden werden. Es ist aber auch ein Runnable, weil es println() auch ohne Parameterliste gibt:

Consumer<String> out = System.out::println;
out.accept( "Kates kurze Kleider" );
Runnable out = System.out::println;
out.run();

Ist eine Hauptmethode mit main(String... args) deklariert, so ist das auch ein Runnable:

Runnable r = JavaApplication1::main;

Anders wäre das bei main(String[]), hier ist ein Parameter zwingend, doch ein Vararg kann auch leer sein.

Anstatt den Namen einer Referenzvariablen zu wählen, kann auch this das Objekt beschreiben, und auch super ist möglich. this ist praktisch, wenn die Implementierung einer funktionalen Schnittstelle auf eine Methode der eigenen Klasse delegieren möchte. Wenn zum Beispiel eine lokale Methode compareTrimmed(…) in der Klasse existieren würde, in der auch der Lambda-Ausdruck steht, und wenn diese Methode als Comparator in Arrays.sort(…) verwendet werden sollte, könnte es heißen: Arrays.sort(words, this::compareTrimmed).

[+]Hinweis

Es ist nicht möglich eine spezielle Methode über die Methodenreferenz auszuwählen. Eine Angabe wie String::valueOf oder Arrays::sort ist relativ breit – bei Letzterem wählt der Compiler eine der 18 passenden überladenen Methoden aus. Da kann es passieren, dass der Compiler eine falsche Methode auswählt. In dem Fall muss ein expliziter Lambda-Ausdruck eine Mehrdeutigkeit auflösen. Bei generischen Typen kann zum Beispiel List<String>::length oder auch List::length stehen, auch hier erkennt der Compiler wieder alles selbst.

Was soll das alles?

Einem Einsteiger in die Sprache Java wird dieses Sprache-Feature wie der größte Zauber auf Erden vorkommen, und auch Java-Profis bekommen hier zittrige Finger, entweder vor Furcht oder Aufregung … In der Vergangenheit musste in Java sehr viel Code explizit geschrieben werden, aber mit diesen neuen Methoden-Referenzen erkennt und macht der Compiler vieles von selbst.

Nützlich wird diese Eigenschaft mit den funktionalen Bibliotheken bei der Stream-API aus Java 8, die ein eigenes Kapitel im zweiten Band einnehmen. Hier nur ein kurzer Vorgeschmack:

Object[] words = { " ", '3', null, "2", 1, "" };
Arrays.stream( words )
.filter( Objects::nonNull )
.map( Objects::toString )
.map( String::trim )
.filter( s -> ! s.isEmpty() )
.map( Integer::parseInt )
.sorted()
.forEach( System.out::println ); // 1 2 3

 


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
 Zum Katalog
Zum Katalog: Java ist auch eine Insel Java ist auch eine Insel
Jetzt bestellen

 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Java SE 8 Standard-Bibliothek
Java SE 8 Standard-Bibliothek


Zum Katalog: Professionell entwickeln mit Java EE 7
Professionell entwickeln mit Java EE 7


Zum Katalog: Schrödinger programmiert Java
Schrödinger programmiert Java


Zum Katalog: Einführung in Java
Einführung in Java


Zum Katalog: Programmieren lernen mit Java
Programmieren lernen mit Java


Zum Katalog: Apps entwickeln für Android 5
Apps entwickeln für Android 5


Zum Katalog: Apps entwickeln mit Android Studio
Apps entwickeln mit Android Studio


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2016
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de