1. Funksjonsmetoder
Hvis et grensesnitt bare har én metode , kan en variabel av den grensesnitttypen tildeles en verdi gitt av et lambda-uttrykk (lambda-funksjon). Slike grensesnitt ble kjent som funksjonelle grensesnitt (etter at Java la til støtte for lambda-funksjoner).
For eksempel har Java grensesnittet Consumer<Type>
, som har accept(Type obj)
metoden. Hvorfor er dette grensesnittet nødvendig?
I Java 8 har samlinger en forEach()
metode som lar deg utføre en handling for hvert element i samlingen . Og her Consumer<T>
brukes det funksjonelle grensesnittet for å overføre handlingen til forEach()
metoden.
Slik kan du vise alle elementene i en samling :
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");
list.forEach( (s) -> System.out.println(s) );
Kompilatoren 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 versjonen er definitivt kortere enn den andre. Og mens kode med lambda-uttrykk er vanskelig å lese, er kode med anonyme indre klasser noen ganger enda vanskeligere å lese.
2. Metodereferanse
Imidlertid kan lambda-uttrykkskoden vår skrives enda kortere.
Først kan du utelate parentesene rundt s
parameteren:
list.forEach( (s) -> System.out.println(s) );
list.forEach( s -> System.out.println(s) );
Dette kan bare gjøres hvis det er én parameter . Hvis det er flere parametere, må du bruke parenteser .
Og for det andre kan du skrive det slik:
list.forEach( System.out::println );
Dette er nøyaktig samme notasjon. Merk at det ikke er noen parenteser etter println
.
Her har vi den samme koden - et metodekall:
object::method
x -> object.method(x)
Tenk på det: vi ønsket å utføre en handling for hvert element i samlingen list
. Hvis handlingen er et enkelt funksjonskall (som f.eks. println()
), er det fornuftig å ganske enkelt sende funksjonen til metoden som en parameter.
Men hvordan forklarer vi kompilatoren at vi ønsker å bestå metoden i stedet for å kalle den? For å gjøre dette, i stedet for punktoperatoren, bruker vi to kolon før metodenavnet. Et enkelt kolon er allerede brukt for å indikere den ternære operatoren.
Dette er den enkleste og mest kompakte notasjonen.
3. Konstruktør
Metodereferanser med doble kolon er veldig nyttige når vi jobber med I/O-strømmer. Dette vil du se litt senere.
I mellomtiden, la oss snakke om 3 populære måter å sende en metodereferanse på:
Referanse til en metode for et objekt
For å sende en referanse til en metode for et objekt, må du skrive noe sånt som . Denne koden tilsvarer .object::method
x -> object.method(x)
Spesialen this
og super
variablene kan brukes som objekt.
Referanse til en metode for en klasse
For å sende en referanse til en statisk metode, må du skrive noe sånt som . Denne koden blir konvertert til kode somclass::method
x -> class.method(x);
Referanse til en konstruktør
En konstruktør oppfører seg på samme måte som en statisk klassemetode, så du kan også sende en referanse til en konstruktør. Slik ser det ut: .class::new
Du kan for eksempel komme rundt typesletting for samlinger og gi toArray()
metoden en referanse til en konstruktør som vil lage den ønskede matrisen:toArray(int[]::new);
GO TO FULL VERSION