---
title: 'Methoden-Referenz von Java 8'
url: 'https://tutego.de/blog/javainsel/2014/03/methoden-referenz-von-java-8'
markdown: 'https://tutego.de/blog/javainsel/2014/03/methoden-referenz-von-java-8.md'
date: '2014-03-23'
description: 'Je größer Software-Systeme 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 geschriebe…'
taxonomy:
  category:
    - Allgemein
    - Insel
    - 'Java 8'
---

# Methoden-Referenz von Java 8

![Illustration einer tropischen Insel mit Palmen und einem hohen Berg](https://tutego.de/blog/javainsel/user/themes/tutego/images/insel-cover.jpg)# Java Blog für Programmierer

[Java Blog für Programmierer](https://tutego.de/blog/javainsel/)

## Methoden-Referenz von Java 8

23.03.2014 · [Christian Ullenboom](https://tutego.de/blog/javainsel/author/admin/)

Je größer Software-Systeme 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:

```java
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, so dass 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

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

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

```java
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:

```java
Comparator                  c1 = StringUtils::compareTrimmed;
BiFunction c2 = StringUtils::compareTrimmed;
```

#### Varianten von Methoden-Referenzen

Im Beispiel ist die Methode `compareTrimmed(…)` statisch, und links vom Doppelpunkt steht der Name eines Typs. Allerdings kann beim Einsatz eines Typnamen die Methode auch nicht-statisch 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.

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

```java
String string = "Goll";
Supplier 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.

```java
Consumer 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`:

```java
Runnable r = JavaApplication1::main;
```

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

Statt dass der Name einer Referenzvariablen gewählt wird, 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 Klassen existieren würde, in der auch der Lambda-Ausdruck steht, und sollte diese Methode als `Comparator` in `Arrays.sort(…)` verwendet werden, 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 überladen 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 aus Java 8, die ein eigenes Kapitel einnehmen. Hier nur ein kurzer Vorgeschmack:

```java
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
```

Kategorien: [Allgemein](https://tutego.de/blog/javainsel/category/allgemein/), [Insel](https://tutego.de/blog/javainsel/category/insel/), [Java 8](https://tutego.de/blog/javainsel/category/java-8/)

[← Alle Beiträge](https://tutego.de/blog/javainsel/)

---

## Navigation

- Previous: [Klassen mit einer abstrakten Methode als funktionale Schnittstelle?](https://tutego.de/blog/javainsel/2014/03/java-8-abstrakten-methode-als-funktionale-schnittstelle-lambda-ausdruck.md)
- Next: [Java Inseln bald in den Formaten PDF, EPUB und MOBI](https://tutego.de/blog/javainsel/2014/03/java-inseln-bald-in-den-formaten-pdf-epub-und-mobi.md)
