1. Függvénymódszerek

Ha egy interfésznek csak egy metódusa van , akkor az adott interfész típusú változóhoz lambda-kifejezés (lambda-függvény) által adott érték rendelhető . Az ilyen interfészek funkcionális interfészekként váltak ismertté (miután a Java hozzáadta a lambda funkciók támogatását).

Például a Java-nak van a Consumer<Type>felülete, amelyen a accept(Type obj)metódus. Miért van szükség erre a felületre?

A Java 8-ban a gyűjteményeknek van egy forEach()metódusa, amely lehetővé teszi, hogy a gyűjtemény egyes elemeihez valamilyen műveletet hajtson végre . És itt a funkcionális felületet használják a művelet átadására a metódusnak. Consumer<T>forEach()

A következőképpen jelenítheti meg a gyűjtemény összes elemét :

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach( (s) -> System.out.println(s) );
Egy gyűjtemény összes elemének megjelenítése (lambda kifejezés használatával)

A fordító a fenti kódot az alábbi kódra konvertálja:

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));
   }
});
Egy gyűjtemény összes elemének megjelenítése (anonim osztály használatával)

Az első verzió határozottan rövidebb, mint a második. És bár a lambda-kifejezéseket tartalmazó kód nehezen olvasható, a névtelen belső osztályokkal rendelkező kód néha még nehezebben olvasható.



2. Módszer hivatkozás

A lambda kifejezés kódja azonban még rövidebbre is írható.

Először is elhagyhatja a paraméter körüli zárójelekets :

list.forEach( (s) -> System.out.println(s) );
Előtt
list.forEach( s -> System.out.println(s) );
Után

Ezt csak akkor lehet megtenni, ha van egy paraméter . Ha több paraméter is van , akkor zárójeleket kell használnia .

Másodszor pedig így írhatod:

list.forEach( System.out::println );
A legkompaktabb jelölés

Ez pontosan ugyanaz a jelölés. Vegye figyelembe, hogy a . után nincs zárójel println.

Itt ugyanaz a kód van - egy metódushívás:

object::method
x -> object.method(x)

Gondoljunk csak bele: a gyűjtemény minden egyes eleméhez szeretnénk valamilyen műveletet végrehajtani list. Ha a művelet egyetlen függvényhívás (például println()), akkor logikus, hogy egyszerűen átadja a függvényt a metódusnak paraméterként.

De hogyan magyarázzuk el a fordítónak, hogy inkább át akarjuk adni a metódust, mint meghívni? Ehhez a pont operátor helyett két kettőspontot használunk a metódus neve előtt. Egy kettőspont már használatos a háromtagú operátor jelzésére.

Ez a legegyszerűbb és legkompaktabb jelölés.



3. Konstruktor

A kettős kettőspontos metódushivatkozások nagyon hasznosak, ha I/O adatfolyamokkal dolgozunk. Ezt egy kicsit később látni fogod.

Addig is beszéljünk a módszerreferencia átadásának 3 népszerű módjáról:

Hivatkozás egy objektum metódusára

Egy objektum metódusára való hivatkozás átadásához valami ilyesmit kell írnia . Ez a kód egyenértékű a .object::method
x -> object.method(x)

A speciális thisés supera változók használhatók objektumként.

Hivatkozás egy osztály metódusára

Egy statikus metódusra való hivatkozás átadásához valami ilyesmit kell írnia . Ez a kód kódszerűvé alakul átclass::methodx -> class.method(x);

Konstruktorra való hivatkozás

A konstruktor hasonlóan viselkedik, mint egy statikus osztálymetódus, így hivatkozást is átadhatunk egy konstruktornak. Így néz ki: .class::new

Például megkerülheti a gyűjtemények típustörlését, és átadhat a toArray()metódusnak egy hivatkozást egy konstruktornak, amely létrehozza a kívánt tömböt:toArray(int[]::new);