1. Functiemethoden
Als een interface slechts één methode heeft , kan aan een variabele van dat interfacetype een waarde worden toegewezen die wordt gegeven door een lambda-expressie (lambda-functie). Dergelijke interfaces werden bekend als functionele interfaces (nadat Java ondersteuning voor lambda-functies had toegevoegd).
Java heeft bijvoorbeeld de Consumer<Type>
interface, die de accept(Type obj)
methode heeft. Waarom is deze interface nodig?
In Java 8 hebben verzamelingen een forEach()
methode waarmee u voor elk element van de verzameling een actie kunt uitvoeren . En hier wordt de functionele interface gebruikt om de actie door te geven aan de methode. Consumer<T>
forEach()
Zo kunt u alle elementen van een verzameling weergeven :
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");
list.forEach( (s) -> System.out.println(s) );
De compiler converteert de bovenstaande code naar de onderstaande code:
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");
list.forEach(new Consumer<String>()
{
public void accept(String s)
{
System.out.println(s));
}
});
De eerste versie is beslist korter dan de tweede. En hoewel code met lambda-expressies moeilijk te lezen is, is code met anonieme innerlijke klassen soms zelfs nog moeilijker te lezen.
2. Methodereferentie
Onze lambda-expressiecode kan echter nog korter worden geschreven.
Ten eerste kunt u de haakjes rond de s
parameter weglaten:
list.forEach( (s) -> System.out.println(s) );
list.forEach( s -> System.out.println(s) );
Dit kan alleen worden gedaan als er één parameter is . Als er meerdere parameters zijn, moet u haakjes gebruiken .
En ten tweede kun je het zo schrijven:
list.forEach( System.out::println );
Dit is exact dezelfde notatie. Merk op dat er geen haakjes achter de println
.
Hier hebben we dezelfde code — een methodeaanroep:
object::method
x -> object.method(x)
Denk er eens over na: we wilden een actie uitvoeren voor elk element van de list
collectie. Als de actie een enkele functieaanroep is (zoals println()
), dan is het logisch om de functie gewoon als parameter aan de methode door te geven.
Maar hoe leggen we de compiler uit dat we de methode willen doorgeven in plaats van deze te noemen? Om dit te doen, gebruiken we in plaats van de puntoperator twee dubbele punten voor de naam van de methode. Er wordt al een enkele dubbele punt gebruikt om de ternaire operator aan te geven.
Dit is de eenvoudigste en meest compacte notatie.
3. Constructeur
Methodeverwijzingen met dubbele dubbele punten zijn erg handig als we met I/O-streams werken. Dit zie je iets later.
Laten we het in de tussentijd hebben over 3 populaire manieren om een methodereferentie door te geven:
Verwijzing naar een methode van een object
Om een verwijzing naar een methode van een object door te geven, moet u iets schrijven als . Deze code is gelijk aan .object::method
x -> object.method(x)
De speciale this
en super
variabelen kunnen als object worden gebruikt.
Verwijzing naar een methode van een klasse
Om een verwijzing naar een statische methode door te geven, moet u iets schrijven als . Deze code wordt geconverteerd naar code-achtigclass::method
x -> class.method(x);
Verwijzing naar een constructeur
Een constructor gedraagt zich op dezelfde manier als een statische klassemethode, dus u kunt ook een verwijzing naar een constructor doorgeven. Zo ziet het eruit: .class::new
U kunt bijvoorbeeld het wissen van typen voor verzamelingen omzeilen en de toArray()
methode een verwijzing doorgeven aan een constructor die de gewenste array zal maken:toArray(int[]::new);
GO TO FULL VERSION