Der Doppelpunkt-Operator in Java 8

Der Doppelpunkt-Operator in Java 8

1. Überblick

In diesem kurzen Artikel werden diedouble colon operator (::) in Java 8 erläutert und die Szenarien erläutert, in denen der Operator verwendet werden kann.

Weitere Lektüre:

Java 8 Interview Fragen (+ Antworten)

Eine Reihe von beliebten Java8-bezogenen Interviewfragen und natürlich Antworten.

Read more

Anleitung zu Java 8 Optional

Schnelle und praktische Anleitung zu Optional in Java 8

Read more

Neue Funktionen in Java 8

Eine kurze Einführung in die neuen Funktionen von Java 8; Der Fokus liegt auf Standard- und statischen Schnittstellenmethoden, statischen Methodenreferenzen und Optional.

Read more

2. Von Lambdas zum Double Colon Operator

Mit Lambdas-Ausdrücken haben wir gesehen, dass Code sehr präzise werden kann.

Fürcreate a comparator reicht beispielsweise die folgende Syntax aus:

Comparator c = (Computer c1, Computer c2) -> c1.getAge().compareTo(c2.getAge());

Dann mit Typinferenz:

Comparator c = (c1, c2) -> c1.getAge().compareTo(c2.getAge());

Aber können wir den obigen Code noch aussagekräftiger und lesbarer machen? Werfen wir einen Blick:

Comparator c = Comparator.comparing(Computer::getAge);

Wir haben den Operator::als Abkürzung für Lambdas verwendet, die eine bestimmte Methode aufrufen - nach Namen. Und das Ergebnis ist natürlich eine noch besser lesbare Syntax.

3. Wie funktioniert es?

Ganz einfach ausgedrückt, wenn wir eine Methodenreferenz verwenden - die Zielreferenz wird vor dem Trennzeichen:: platziert und der Name der Methode wird danach angegeben.

Zum Beispiel:

Computer::getAge;

Wir betrachten einen Methodenverweis auf die in der KlasseComputerdefinierte MethodegetAge.

Wir können dann mit dieser Funktion arbeiten:

Function getAge = Computer::getAge;
Integer computerAge = getAge.apply(c1);

Beachten Sie, dass wir auf die Funktion verweisen und sie dann auf die richtige Art von Argument anwenden.

4. Methodenreferenzen

Wir können diesen Operator in einigen Szenarien gut gebrauchen.

4.1. Eine statische Methode

Zuerst werden wira static utility method verwenden:

List inventory = Arrays.asList(
  new Computer( 2015, "white", 35), new Computer(2009, "black", 65));
inventory.forEach(ComputerUtils::repair);

4.2. Eine Instanzmethode eines vorhandenen Objekts

Schauen wir uns als nächstes ein interessantes Szenario an -referencing a method of an existing object instance.

Wir werden die VariableSystem.out verwenden - ein Objekt vom TypPrintStream, das die Methodeprint unterstützt:

Computer c1 = new Computer(2015, "white");
Computer c2 = new Computer(2009, "black");
Computer c3 = new Computer(2014, "black");
Arrays.asList(c1, c2, c3).forEach(System.out::print);

4.3. Eine Instanzmethode eines beliebigen Objekts eines bestimmten Typs

Computer c1 = new Computer(2015, "white", 100);
Computer c2 = new MacbookPro(2009, "black", 100);
List inventory = Arrays.asList(c1, c2);
inventory.forEach(Computer::turnOnPc);

Wie Sie sehen können, verweisen wir auf dieturnOnPc-Methode nicht auf eine bestimmte Instanz, sondern auf den Typ selbst.

In Zeile 4 wird für jedes Objekt voninventory die InstanzmethodeturnOnPc aufgerufen.

Und dies bedeutet natürlich, dass - fürc1 die MethodeturnOnPc für die InstanzComputerund fürc2 für die InstanzMacbookProaufgerufen wird.

4.4. Eine Supermethode eines bestimmten Objekts

Angenommen, Sie haben die folgende Methode in der Oberklasse vonComputer:

public Double calculateValue(Double initialValue) {
    return initialValue/1.50;
}

und diese inMacbookPro Unterklasse:

@Override
public Double calculateValue(Double initialValue){
    Function function = super::calculateValue;
    Double pcValue = function.apply(initialValue);
    return pcValue + (initialValue/10) ;
}

Ein Aufruf der MethodecalculateValuefür eine Instanz vonMacbookPro:

macbookPro.calculateValue(999.99);

erzeugt auch einen Aufruf voncalculateValue in der SuperklasseComputer.

5. Konstruktorreferenzen

5.1. Erstellen Sie eine neue Instanz

Das Referenzieren eines Konstruktors zum Instanziieren eines Objekts kann recht einfach sein:

@FunctionalInterface
public interface InterfaceComputer {
    Computer create();
}

InterfaceComputer c = Computer::new;
Computer computer = c.create();

Was ist, wenn Sie zwei Parameter in einem Konstruktor haben?

BiFunction c4Function = Computer::new;
Computer c4 = c4Function.apply(2013, "white");

Bei drei oder mehr Parametern müssen Sie eine neue Funktionsschnittstelle definieren:

@FunctionalInterface
interface TriFunction {
    R apply(A a, B b, C c);
    default  TriFunction andThen( Function after) {
        Objects.requireNonNull(after);
        return (A a, B b, C c) -> after.apply(apply(a, b, c));
    }
}

Initialisieren Sie dann Ihr Objekt:

TriFunction  c6Function = Computer::new;
Computer c3 = c6Function.apply(2008, "black", 90);

5.2. Erstellen Sie ein Array

Lassen Sie uns abschließend sehen, wie Sie ein Array vonComputer-Objekten mit fünf Elementen erstellen:

Function  computerCreator = Computer[]::new;
Computer[] computerArray = computerCreator.apply(5);

6. Fazit

Wie wir sehen, wird der in Java 8 eingeführte Doppelpunktoperator in einigen Szenarien und insbesondere in Verbindung mit Streams sehr nützlich sein.

Es ist auch sehr wichtig, sich die funktionalen Schnittstellen anzusehen, um besser zu verstehen, was hinter den Kulissen passiert.

Das vollständigesource code für das Beispiel ist inthis GitHub project verfügbar - dies ist ein Maven- und Eclipse-Projekt, damit es importiert und unverändert verwendet werden kann.