Programovanie

Začnite s odkazmi na metódy v prostredí Java

Spolu s lambdas priniesla Java SE 8 odkazy na metódy v jazyku Java. Tento tutoriál ponúka stručný prehľad referencií na metódy v Jave a potom ich začne používať s príkladmi kódu Java. Na konci tutoriálu budete vedieť, ako používať odkazy na metódy k odkazu na statické metódy triedy, viazané a neviazané nestatické metódy a konštruktory, ako aj to, ako ich používať na odkazy na inštančné metódy v nadtriede a aktuálnej triede typy. Pochopíte tiež, prečo mnoho vývojárov Java prijalo výrazy lambda a odkazy na metódy ako čistejšiu a jednoduchšiu alternatívu k anonymným triedam.

Upozorňujeme, že príklady kódov v tomto tutoriále sú kompatibilné s JDK 12.

stiahnuť Získajte kód Stiahnite si zdrojový kód napríklad pre aplikácie v tejto príručke. Vytvoril Jeff Friesen pre JavaWorld.

Odkazy na metódu: Primér

Môj predchádzajúci výukový program Java 101 predstavil výrazy lambda, ktoré sa používajú na definovanie anonymných metód, ktoré sa potom môžu považovať za inštancie funkčného rozhrania. Niekedy výraz lambda neurobí nič iné, ako zavolať existujúcu metódu. Napríklad nasledujúci fragment kódu používa na vyvolanie lambdu System.outje neplatné výtlačky metóda na jediný argument lambda -styp zatiaľ nie je známy:

(s) -> System.out.println (s)

Lambda predstavuje s ako jeho formálny zoznam parametrov a telo kódu, ktorého System.out.println (s) výrazové výtlačky shodnota pre štandardný výstupný tok. Nemá explicitný typ rozhrania. Namiesto toho kompilátor odvodzuje z okolitého kontextu, ktoré funkčné rozhranie má vytvoriť inštanciu. Zvážte napríklad nasledujúci fragment kódu:

Spotrebiteľ spotrebiteľ = (s) -> System.out.println (s);

Kompilátor analyzuje predchádzajúcu deklaráciu a určuje, že java.util.function.Consumer preddefinované funkčné rozhranie neplatnosť prijať (T t) metóda zodpovedá formálnemu zoznamu parametrov lambda (s). To tiež určuje súhlasiť()je neplatný zhoduje sa s návratovým typom println ()je neplatný návratový typ. Lambda je teda viazaný do Spotrebiteľ.

Presnejšie povedané, lambda je viazaná na Spotrebiteľ. Kompilátor generuje kód tak, aby vyvolal Spotrebiteľje void accept (reťazce) Výsledkom metódy je reťazcový argument odovzdaný s sa odovzdáva System.outje void println (String s) metóda. Toto vyvolanie je uvedené nižšie:

consumer.accept („Dobrý deň“); // Odošlite „Hello“ do tela lambda. Tlač Ahoj na štandardný výstup.

Ak chcete ušetriť stlačenie klávesov, môžete lambdu nahradiť znakom odkaz na metódu, čo je kompaktný odkaz na existujúcu metódu. Napríklad nahrádza nasledujúci fragment kódu (Reťazce) -> System.out.println (s) s System.out :: println, kde :: znamená to System.outje void println (String s) metóda sa odkazuje:

Spotrebiteľ consumer2 = System.out :: println; // Odkaz na metódu je kratší. consumer2.accept ("Hello"); // Odošlite „Hello“ do tela lambda. Tlač Ahoj na štandardný výstup.

Nie je potrebné zadávať formálny zoznam parametrov pre predchádzajúcu referenciu metódy, pretože kompilátor môže tento zoznam odvodiť na základe Spotrebiteľ Tento parametrizovaný typ java.lang.String skutočný typ argumentu nahradí T v neplatnosť prijať (T t), a je tiež typom jediného parametra v tele lambda System.out.println () volanie metódy.

Podrobný odkaz na metódu

A odkaz na metódu je syntaktická skratka pre vytvorenie lambda z existujúcej metódy. Namiesto poskytnutia implementačného tela odkaz na metódu odkazuje na metódu existujúcej triedy alebo objektu. Rovnako ako v prípade lambda, odkaz na metódu vyžaduje cieľový typ.

Odkazy na metódy môžete použiť na označenie statických metód triedy, viazaných a neviazaných nestatických metód a konštruktorov. Môžete tiež použiť odkazy na metódy na označenie inštančných metód v nadtriedach a aktuálnych typoch tried. Predstavím vám každú z týchto referenčných kategórií metód a v malej ukážke ukážem, ako sa používajú.

Získajte viac informácií o odkazoch na metódy

Po prečítaní tejto časti si prečítajte Referencie metód v Jave 8 (Toby Weston, február 2014), kde získate viac informácií o referenciách metód v viazaných a neviazaných nestatických kontextoch metód.

Odkazy na statické metódy

A odkaz na statickú metódu odkazuje na statickú metódu v konkrétnej triede. Jeho syntax je className::staticMethodName, kde className identifikuje triedu a staticMethodName identifikuje statickú metódu. Príkladom je Celé číslo :: bitCount. Výpis 1 demonštruje odkaz na statickú metódu.

Zoznam 1. MRDemo.java (verzia 1)

importovať java.util.Arrays; import java.util.function.Consumer; verejná trieda MRDemo {public static void main (String [] args) {int [] pole = {10, 2, 19, 5, 17}; Spotrebiteľ spotrebiteľ = Pole :: triediť; consumer.accept (pole); pre (int i = 0; i <pole.length; i ++) System.out.println (pole [i]); System.out.println (); int [] pole2 = {19, 5, 14, 3, 21, 4}; Spotrebiteľ consumer2 = (a) -> Arrays.sort (a); consumer2.accept (pole2); pre (int i = 0; i <pole2.length; i ++) System.out.println (pole2 [i]); }}

Zoznam 1 hlavný() metóda triedi dvojicu celočíselných polí cez java.util.Arrays triedy static void sort (int [] a) metóda, ktorá sa objavuje v statických odkazoch na metódy a ekvivalentných kontextoch výrazov lambda. Po vytriedení poľa a pre loop vytlačí obsah zoradeného poľa do štandardného výstupného toku.

Predtým, ako budeme môcť použiť referenciu na metódu alebo lambdu, musí byť viazaná na funkčné rozhranie. Používam preddefinované Spotrebiteľ funkčné rozhranie, ktoré spĺňa požiadavky na referenciu metódy / lambda. Operácia triedenia sa začína odovzdaním poľa, do ktorého sa má triediť Spotrebiteľje súhlasiť() metóda.

Zostaviť zoznam 1 (javac MRDemo.java) a spustite aplikáciu (java MRDemo). Budete sledovať nasledujúci výstup:

2 5 10 17 19 3 4 5 14 19 21

Odkazy na viazané nestatické metódy

A viazaný odkaz na nestatickú metódu označuje nestatickú metódu, ktorá je viazaná na a prijímač objekt. Jeho syntax je objectName::instanceMethodName, kde objectName identifikuje príjemcu a instanceMethodName identifikuje metódu inštancie. Príkladom je s :: trim. Výpis 2 demonštruje viazaný nestatický odkaz na metódu.

Zoznam 2. MRDemo.java (verzia 2)

import java.util.function.Supplier; verejná trieda MRDemo {public static void main (String [] args) {String s = "Rýchla hnedá líška preskočila lenivého psa"; tlač (s :: dĺžka); print (() -> s.length ()); print (new Supplier () {@Override public Integer get () {return s.length (); // zatvára nad s}}); } verejná statická neplatná tlač (dodávateľ dodávateľa) {System.out.println (dodávateľ.get ()); }}

Zoznam 2 hlavný() metóda priradí reťazec String premenná s a potom vyvolá print () metóda triedy s funkčnosťou na získanie dĺžky tohto reťazca ako argumentu tejto metódy. print () je vyvolaná v referencii metódy (s :: dĺžka -- dĺžka () je viazaný na s), ekvivalentná lambda a ekvivalentné kontexty anonymných tried.

Definoval som print () používať java.util.function.Supplier preddefinované funkčné rozhranie, ktorého dostať () metóda vráti dodávateľa výsledkov. V takom prípade Dodávateľ inštancia odovzdaná print () realizuje svoje dostať () spôsob návratu s.length (); print () výstupy tejto dĺžky.

s :: dĺžka zavádza uzáver, ktorý sa zatvára nad s. Vidíte to jasnejšie na príklade lambda. Pretože lambda nemá žiadne argumenty, hodnota s je k dispozícii iba z priloženého rozsahu. Preto je telo lambda uzáverom, ktorý sa zatvára s. Príklad anonymnej triedy to robí ešte jasnejším.

Zostavte Výpis 2 a spustite aplikáciu. Budete sledovať nasledujúci výstup:

44 44 44

Odkazy na neviazané nestatické metódy

An neviazaný odkaz na nestatickú metódu odkazuje na nestatickú metódu, ktorá nie je viazaná na objekt prijímača. Jeho syntax je className::instanceMethodName, kde className identifikuje triedu, ktorá deklaruje inštančnú metódu a instanceMethodName identifikuje metódu inštancie. Príkladom je String :: toLowerCase.

String :: toLowerCase je neviazaný nestatický odkaz na metódu, ktorý identifikuje nestatický Reťazec toLowerCase () metóda String trieda. Pretože však statická metóda stále vyžaduje objekt prijímača (v tomto príklade a String objekt, ktorý sa používa na vyvolanie toLowerCase () prostredníctvom odkazu na metódu) je objekt prijímača vytvorený virtuálnym strojom. toLowerCase () bude vyvolaná pre tento objekt. String :: toLowerCase určuje metódu, ktorá trvá jeden String argument, ktorý je objektom prijímača, a vráti a String výsledok. String :: toLowerCase () je ekvivalentná lambda (Reťazec s) -> {return s.toLowerCase (); }.

Výpis 3 demonštruje tento neviazaný nestatický odkaz na metódu.

Zoznam 3. MRDemo.java (verzia 3)

import java.util.function.Function; public class MRDemo {public static void main (String [] args) {print (String :: toLowerCase, "STRING TO LOWERCASE"); print (s -> s.toLowerCase (), „STRING TO LOWERCASE“); print (new Function () {@Override public String apply (String s) // prijíma argumenty v parametroch s; {// nemusí uzatvárať s návratom s.toLowerCase ();}}, „STRING TO LOWERCASE“ ); } public static void print (Function function, String s) {System.out.println (function.apply (s)); }}

Zoznam 3 hlavný() metóda vyvolá print () metóda triedy s funkčnosťou na prevod reťazca na malé písmená a reťazec, ktorý sa má previesť ako argumenty metódy. print () je vyvolaná v referencii metódy (String :: toLowerCase, kde toLowerCase () nie je viazaný na objekt zadaný používateľom) a ekvivalentné kontexty lambda a anonymnej triedy.

Definoval som print () používať java.util.funkcia.Funkcia preddefinované funkčné rozhranie, ktoré predstavuje funkciu, ktorá prijíma jeden argument a vytvára výsledok. V takom prípade Funkcia inštancia odovzdaná print () realizuje svoje R platí (T t) spôsob návratu s.toLowerCase (); print () výstup tohto reťazca.

Napriek tomu String časť String :: toLowerCase vyzerá to, že sa odkazuje na triedu, odkazuje sa iba na inštanciu tejto triedy. Príklad anonymnej triedy to robí zreteľnejším. Upozorňujeme, že v príklade anonymnej triedy dostane lambda argument; nezatvára sa nad parametrom s (t.j. nejde o uzávierku).

Zostavte zoznam 3 a spustite aplikáciu. Budete sledovať nasledujúci výstup:

reťazec na malé písmená reťazec na malé písmená reťazec na malé písmená

Odkazy na konštruktérov

Môžete použiť odkaz na metódu na odkaz na konštruktor bez vytvorenia inštancie pomenovanej triedy. Tento druh odkazu na metódu je známy ako a referencia konštruktora. Jeho syntax je className::Nový. className musí podporovať vytváranie objektov; nemôže pomenovať abstraktnú triedu alebo rozhranie. Kľúčové slovo Nový pomenuje odkazovaný konštruktor. Tu je niekoľko príkladov:

  • Postava :: nová: zodpovedá lambda (Znak ch) -> nový Znak (ch)
  • Dlhé :: nové: zodpovedá lambda (dlhá hodnota) -> nová dlhá (hodnota) alebo (Reťazce) -> nové Long (s)
  • ArrayList :: nový: zodpovedá lambda () -> nový ArrayList ()
  • plavák [] :: nový: zodpovedá lambda (int veľkosť) -> nový plavák [veľkosť]

Posledný referenčný príklad konštruktora určuje typ poľa namiesto typu triedy, ale princíp je rovnaký. Príklad ukazuje referencia konštruktora poľa na „konštruktor“ typu poľa.

Ak chcete vytvoriť odkaz na konštruktor, zadajte Nový bez konštruktéra. Keď trieda ako napr java.lang.Dlhé deklaruje viac konštruktorov, kompilátor porovná typ funkčného rozhrania so všetkými konštruktormi a vyberie najlepšiu zhodu. Výpis 4 demonštruje odkaz na konštruktor.

Zoznam 4. MRDemo.java (verzia 4)

import java.util.function.Supplier; verejná trieda MRDemo {public static void main (String [] args) {dodávateľ dodávateľa = MRDemo :: nový; System.out.println (supplier.get ()); }}

Zoznam 4 MRDemo :: nové odkaz na konštruktor je ekvivalentný s lambda () -> nové MRDemo (). Vyjadrenie supply.get () vykoná túto lambdu, ktorá vyvolá MRDemopredvolený konštruktor bez argumentov a vráti MRDemo objekt, ktorý je odovzdaný System.out.println (). Táto metóda prevedie objekt na reťazec, ktorý vytlačí.

Teraz predpokladajme, že máte triedu s konštruktorom bez argumentov a konštruktorom, ktorý berie argument, a chcete zavolať konštruktoru, ktorý berie argument. Túto úlohu môžete vykonať výberom iného funkčného rozhrania, napríklad preddefinovaného Funkcia rozhranie zobrazené v zozname 5.

Zoznam 5. MRDemo.java (verzia 5)

import java.util.function.Function; verejná trieda MRDemo {súkromné ​​meno reťazca; MRDemo () {name = ""; } MRDemo (názov reťazca) {this.name = meno; System.out.printf ("MRDemo (názov reťazca) volaný s% s% n", meno); } public static void main (String [] args) {Function function = MRDemo :: new; System.out.println (function.apply ("nejaké meno")); }}

Funkčná funkcia = MRDemo :: nový; spôsobí, že kompilátor vyhľadá konštruktor, ktorý vezme a String argument, pretože Funkciaje použiť () metóda vyžaduje jeden (v tomto kontexte) String argument. Vykonávanie function.apply ("nejaké meno") výsledky v „nejaké meno“ sa odovzdáva MRDemo (názov reťazca).

$config[zx-auto] not found$config[zx-overlay] not found