1. Funktionsmetoder
Hvis en grænseflade kun har én metode , kan en variabel af denne grænsefladetype tildeles en værdi givet af et lambda-udtryk (lambda-funktion). Sådanne grænseflader blev kendt som funktionelle grænseflader (efter Java tilføjede understøttelse af lambda-funktioner).
For eksempel har Java grænsefladen Consumer<Type>
, som har accept(Type obj)
metoden. Hvorfor er denne grænseflade nødvendig?
I Java 8 har samlinger en forEach()
metode, som lader dig udføre en handling for hvert element i samlingen . Og her Consumer<T>
bruges den funktionelle grænseflade til at videregive handlingen til forEach()
metoden.
Sådan kan du vise alle elementer i en samling :
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");
list.forEach( (s) -> System.out.println(s) );
Compileren vil konvertere koden ovenfor til koden nedenfor:
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));
}
});
Den første version er bestemt kortere end den anden. Og mens kode med lambda-udtryk er svær at læse, er kode med anonyme indre klasser nogle gange endnu sværere at læse.
2. Metodehenvisning
Vores lambda- udtrykskode kan dog skrives endnu kortere.
Først kan du udelade parenteserne omkring s
parameteren:
list.forEach( (s) -> System.out.println(s) );
list.forEach( s -> System.out.println(s) );
Dette kan kun gøres, hvis der er én parameter . Hvis der er flere parametre, skal du bruge parenteser .
Og for det andet kan du skrive det sådan:
list.forEach( System.out::println );
Dette er nøjagtig den samme notation. Bemærk, at der ikke er nogen parentes efter println
.
Her har vi den samme kode - et metodekald:
object::method
x -> object.method(x)
Tænk over det: vi ønskede at udføre en handling for hvert element i samlingen list
. Hvis handlingen er et enkelt funktionskald (såsom println()
), så giver det mening blot at videregive funktionen til metoden som en parameter.
Men hvordan forklarer vi compileren, at vi vil videregive metoden i stedet for at kalde den? For at gøre dette bruger vi i stedet for prikoperatoren to koloner før metodenavnet. Et enkelt kolon er allerede brugt til at angive den ternære operator.
Dette er den enkleste og mest kompakte notation.
3. Konstruktør
Metodereferencer med dobbelte koloner er meget praktiske, når vi arbejder med I/O-streams. Det vil du se lidt senere.
Lad os i mellemtiden tale om 3 populære måder at videregive en metodehenvisning på:
Reference til en metode til et objekt
For at videregive en reference til en metode til et objekt, skal du skrive noget som . Denne kode svarer til .object::method
x -> object.method(x)
Specialet this
og super
variablerne kan bruges som objektet.
Reference til en metode i en klasse
For at videregive en henvisning til en statisk metode, skal du skrive noget som . Denne kode bliver konverteret til kode somclass::method
x -> class.method(x);
Reference til en konstruktør
En konstruktør opfører sig på samme måde som en statisk klassemetode, så du kan også videregive en reference til en konstruktør. Sådan ser det ud :.class::new
For eksempel kan du komme uden om typesletning for samlinger og give toArray()
metoden en reference til en konstruktør, der vil skabe det ønskede array:toArray(int[]::new);
GO TO FULL VERSION