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) );
Vise alle elementene i en samling (ved hjelp av et lambda-uttrykk)

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));
   }
});
Vise alle elementene i en samling (ved hjelp av en anonym klasse)

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 sparameteren:

list.forEach( (s) -> System.out.println(s) );
Før
list.forEach( s -> System.out.println(s) );
Etter

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 );
Mest kompakt notasjon

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 thisog supervariablene 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::methodx -> 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);