Programmēšana

Sāciet ar metožu atsaucēm Java

Kopā ar lambdas, Java SE 8 sniedza metodes atsauces uz Java valodu. Šajā apmācībā ir sniegts īss metožu atsauču pārskats Java, pēc tam varat sākt tos izmantot ar Java kodu piemēriem. Apmācības beigās jūs zināt, kā izmantot metožu atsauces, lai atsauktos uz klases statiskajām metodēm, saistītām un nesaistītām nemestatiskām metodēm un konstruktoriem, kā arī to, kā tās izmantot, lai atsauktos uz instanču metodēm virsklasē un pašreizējā klasē. veidi. Jūs arī sapratīsit, kāpēc daudzi Java izstrādātāji ir pieņēmuši lambda izteicienus un metožu atsauces kā tīrāku, vienkāršāku alternatīvu anonīmām klasēm.

Ņemiet vērā, ka šīs apmācības kodu piemēri ir saderīgi ar JDK 12.

lejupielādēt Iegūt kodu Lejupielādējiet šajā apmācībā avota kodu, piemēram, lietojumprogrammām. Izveidoja Jeff Friesen JavaWorld.

Metodes atsauces: grunts

Mana iepriekšējā Java 101 apmācība ieviesa lambda izteiksmes, kas tiek izmantotas, lai definētu anonīmas metodes, kuras pēc tam var uzskatīt par funkcionālās saskarnes gadījumiem. Dažreiz lambda izteiksme nedara neko citu, kā izsaukt esošu metodi. Piemēram, šim koda fragmentam izsaukšanai tiek izmantota lambda System.out's void println (s) metode uz lambda vienīgo argumentu -sveids vēl nav zināms:

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

Lambda dāvanas s) kā tās formālo parametru sarakstu un koda struktūru, kuras System.out.println (s) izteiksmes izdrukas svērtība standarta izejas plūsmai. Tam nav noteikta saskarnes veida. Tā vietā kompilators no apkārtējā konteksta secina, kuru funkcionālo saskarni vajadzētu instancēt. Piemēram, apsveriet šādu koda fragmentu:

Patērētāja patērētājs = (s) -> System.out.println (s);

Kompilators analizē iepriekšējo deklarāciju un nosaka, ka java.util.function.Patērētājs iepriekš definētas funkcionālās saskarnes anulēt akceptēt (T t) metode sakrīt ar lambda formālo parametru sarakstu (s)). Tas arī to nosaka pieņemt ()'s spēkā neesošs atgriešanās tipa spēles println ()'s spēkā neesošs atgriešanās veids. Tādējādi lambda ir saistīts uz Patērētājs.

Konkrētāk, lambda ir saistīta ar Patērētājs. Kompilators ģenerē kodu tā, lai izsauktu Patērētājs's anulēt akceptēt (virknes) metodes rezultātā virknes arguments tiek nodots s tiek nodota System.out's void println (virkne s) metodi. Šis aicinājums ir parādīts zemāk:

patērētājs.pieņemt ("Labdien"); // Nododiet sveicienu lambda ķermenim. Drukāt Sveiki standarta izvadē.

Lai saglabātu taustiņsitienus, lambda var aizstāt ar a metodes atsauce, kas ir kompakta atsauce uz esošu metodi. Piemēram, tiek aizstāts šāds koda fragments (Virkne) -> System.out.println (s) ar System.out :: println, kur :: nozīmē to System.out's void println (virkne s) metode ir atsauce:

Patērētāja patērētājs2 = System.out :: println; Metodes atsauce ir īsāka. patērētājs2.pieņemt ("Labdien"); // Nododiet sveicienu lambda ķermenim. Drukāt Sveiki standarta izvadē.

Iepriekšējai metodes atsaucei nav nepieciešams norādīt formālu parametru sarakstu, jo kompilators var secināt šo sarakstu, pamatojoties uz Patērētājs Šis parametrizētais tips ir java.lang.Strings faktiskā tipa arguments aizstāj T iekšā anulēt akceptēt (T t), un tas ir arī viena parametra tips lambda ķermenī System.out.println () metodes izsaukums.

Metodes padziļināti

A metodes atsauce ir sintaktiskais saīsne lambda izveidei no esošās metodes. Tā vietā, lai nodrošinātu ieviešanas struktūru, metodes atsauce attiecas uz esošās klases vai objekta metodi. Tāpat kā lambda gadījumā, metodes atsaucei nepieciešams mērķa tips.

Varat izmantot metožu atsauces, lai atsauktos uz klases statiskajām metodēm, saistītām un nesaistītām nemestatiskām metodēm un konstruktoriem. Varat arī izmantot metožu atsauces, lai atsauktos uz instanču metodēm virsklasē un pašreizējos klašu tipos. Es jūs iepazīstināšu ar katru no šīm metožu atsauces kategorijām un parādīšu, kā tās tiek izmantotas nelielā demonstrācijā.

Uzziniet vairāk par metožu atsaucēm

Pēc šīs sadaļas izlasīšanas skatiet Java 8 metodikas atsauces (Tobijs Vestons, 2014. gada februāris), lai iegūtu plašāku ieskatu par atsaucēm uz metodēm saistītos un nesaistītos nemestiskos metožu kontekstos.

Atsauces uz statiskām metodēm

A statiskās metodes atsauce attiecas uz statisko metodi noteiktā klasē. Tās sintakse ir className::staticMethodName, kur className identificē klasi un staticMethodName identificē statisko metodi. Piemērs ir Vesels skaitlis :: bitCount. 1. saraksts parāda statiskas metodes atsauci.

1. saraksts. MRDemo.java (1. versija)

importēt java.util.Arrays; importēt java.util.function.Consumer; public class MRDemo {public static void main (String [] args) {int [] masīvs = {10, 2, 19, 5, 17}; Patērētāja patērētājs = Masīvi :: šķirot; patērētājs.pieņemt (masīvs); par (int i = 0; i <masīva.length; i ++) System.out.println (masīvs [i]); System.out.println (); int [] masīvs2 = {19, 5, 14, 3, 21, 4}; Patērētāja patērētājs2 = (a) -> Masīvi. Kārtot (a); patērētājs2.pieņemt (masīvs2); par (int i = 0; i <masīva2.length; i ++) System.out.println (masīvs2 [i]); }}

Sarakstā 1 galvenais () metode sakārto veselu skaitļu masīvu pāri, izmantojot java.util.Arrays klases static void sort (int [] a) metode, kas parādās statiskās metodes atsauces un ekvivalentos lambda izteiksmes kontekstos. Pēc masīva šķirošanas a priekš loop izdrukā sakārtotā masīva saturu standarta izvades straumē.

Pirms mēs varam izmantot metodes atsauci vai lambda, tai jābūt saistītai ar funkcionālo saskarni. Es izmantoju iepriekš definēto Patērētājs funkcionālā saskarne, kas atbilst metodes atsauces / lambda prasībām. Kārtošanas darbība sākas, nododot kārtošanai paredzēto masīvu Patērētājs's pieņemt () metodi.

Sastādīt 1. sarakstu (javac MRDemo.java) un palaidiet lietojumprogrammu (java MRDemo). Jūs ievērosiet šādu rezultātu:

2 5 10 17 19 3 4 5 14 19 21

Atsauces uz saistītām nestatiskām metodēm

A saistītā nestacionārā metodes atsauce attiecas uz nestatisku metodi, kas saistīta ar a uztvērējs objekts. Tās sintakse ir objectName::instanceMethodName, kur objectName identificē uztvērēju un instanceMethodName identificē instances metodi. Piemērs ir s :: apdare. 2. saraksts parāda saistošu atsauces metodi, kas nav statiska.

2. saraksts. MRDemo.java (2. versija)

importēt java.util.function.Supplier; publiskā klase MRDemo {public static void main (String [] args) {String s = "Ātri brūnā lapsa pārlēca slinkajam sunim"; druka (s :: garums); drukāt (() -> s.length ()); drukāt (jauns piegādātājs () {@Override public Integer get () {return s.length (); // aizveras pāri s}}); } public static void print (piegādātāja piegādātājs) {System.out.println (piegādātājs.get ()); }}

Sarakstā 2 galvenais () metode piešķir virkni Stīga mainīgais s un pēc tam izsauc izdrukāt () klases metode ar funkcionalitāti, lai iegūtu šīs virknes garumu kā šīs metodes argumentu. izdrukāt () tiek izsaukts metodes atsaucē (s :: garums -- garums () ir saistīts ar s), ekvivalents lambda un līdzvērtīgs anonīms klases konteksts.

Esmu definējis izdrukāt () izmantot java.util.function.Supplier iepriekš definēts funkcionālais interfeiss, kura gūt() metode atgriež rezultātu piegādātāju. Šajā gadījumā Piegādātājs instance nodota izdrukāt () īsteno to gūt() metode, lai atgrieztos s.length (); izdrukāt () izved šo garumu.

s :: garums ievieš aizvēršanu, kas aizveras s. To skaidrāk var redzēt lambda piemērā. Tā kā lambda nav argumentu, vērtība s ir pieejams tikai pievienotajā sfērā. Tāpēc lambda korpuss ir aizvēršanās, kas aizveras s. Anonīmās klases piemērs to padara vēl skaidrāku.

Sastādiet 2. sarakstu un palaidiet lietojumprogrammu. Jūs ievērosiet šādu rezultātu:

44 44 44

Atsauces uz nesaistītām nestacionārām metodēm

An nesaistīta statiskas metodes atsauce attiecas uz nestatisku metodi, kas nav saistīta ar uztvērēja objektu. Tās sintakse ir className::instanceMethodName, kur className identificē klasi, kas deklarē instances metodi, un instanceMethodName identificē instances metodi. Piemērs ir Stīga :: toLowerCase.

Stīga :: toLowerCase ir nesaistīta non-static metodes atsauce, kas identificē non-static String toLowerCase () metode Stīga klasē. Tomēr, tā kā nav statiska metode joprojām prasa uztvērēja objektu (šajā piemērā a Stīga objekts, ko izmanto, lai izsauktu toLowerCase () izmantojot metodes atsauci), uztvērēja objektu izveido virtuālā mašīna. toLowerCase () tiks izsaukts uz šo objektu. Stīga :: toLowerCase norāda metodi, kas prasa vienu Stīga arguments, kas ir uztvērēja objekts, un atgriež a Stīga rezultāts. Virkne :: toLowerCase () ir līdzvērtīgs lambda (Virkne s) -> {atgriezties s.toLowerCase (); }.

3. uzskaitījums parāda šo nesaistīto atsauces metodi, kas nav statiska.

3. saraksts. MRDemo.java (3. versija)

importēt java.util.function.Function; public class MRDemo {public static void main (String [] args) {print (String :: toLowerCase, "STRING LOWERCASE"); drukāt (s -> s.toLowerCase (), "STRING LOWERCASE"); drukāt (jauna funkcija () {@ Pārvarēt publisko virkni, kas piemērojama (virkne s) // saņem argumentu parametrā s; {// nav jāaizver vairāk nekā s atgriešanās s.toLowerCase ();}}, "STRING LOWERCASE" ); } public static void print (Funkcijas funkcija, String s) {System.out.println (function.apply (s)); }}

Saraksts 3 galvenais () metode izsauc izdrukāt () klases metode ar funkcionalitāti, lai virkni pārveidotu par mazajiem burtiem, un virkne, kas jāpārvērš kā metodes argumenti. izdrukāt () tiek izsaukts metodes atsaucē (Stīga :: toLowerCase, kur toLowerCase () nav saistīts ar lietotāja norādītu objektu) un līdzvērtīgiem lambda un anonīmu klases kontekstiem.

Esmu definējis izdrukāt () izmantot java.util.function.Function iepriekš definēta funkcionālā saskarne, kas attēlo funkciju, kas pieņem vienu argumentu un rada rezultātu. Šajā gadījumā Funkcija instance nodota izdrukāt () īsteno to R piemērot (T t) metode, lai atgrieztos s.toLowerCase (); izdrukāt () izvada šo virkni.

Lai gan Stīga daļa no Stīga :: toLowerCase izskatās, ka atsauce uz klasi ir atsauce tikai uz šīs klases instanci. Anonīmās klases piemērs to padara acīmredzamāku. Ņemiet vērā, ka anonīmā klases piemērā lambda saņem argumentu; tas netiek aizvērts pāri parametram s (t.i., tas nav slēgšana).

Sastādiet 3. sarakstu un palaidiet lietojumprogrammu. Jūs ievērosiet šādu rezultātu:

virkne uz mazo virkni uz mazo virkni uz mazo

Atsauces uz konstruktoriem

Metodes atsauci var izmantot, lai atsauktos uz konstruktoru, nepaziņojot nosaukto klasi. Šāda veida metodes atsauces ir pazīstamas kā a konstruktora atsauce. Tās sintakse ir className:: jauns. className jāatbalsta objektu veidošana; tā nevar nosaukt abstraktu klasi vai saskarni. Atslēgvārds jauns nosauc atsauces konstruktoru. Šeit ir daži piemēri:

  • Raksturs :: jauns: ekvivalents lambda (Rakstzīme ch) -> jauns raksturs (ch)
  • Garš :: jauns: ekvivalents lambda (garā vērtība) -> jauna Garā (vērtība) vai (Stīgas) -> jaunas garās (-ās)
  • ArrayList :: jauns: ekvivalents lambda () -> jauns ArrayList ()
  • pludiņš [] :: jauns: ekvivalents lambda (int izmērs) -> jauns pludiņš [izmērs]

Pēdējā konstruktora atsauces piemērā klases tipa vietā tiek norādīts masīva tips, bet princips ir vienāds. Piemērs parāda masīva konstruktora atsauce masīva tipa "konstruktoram".

Lai izveidotu konstruktora atsauci, norādiet jauns bez konstruktora. Kad tāda klase kā java.lang.Long deklarē vairākus konstruktorus, sastādītājs salīdzina funkcionālā interfeisa tipu ar visiem konstruktoriem un izvēlas labāko atbilstību. 4. saraksts parāda konstruktora atsauci.

4. saraksts. MRDemo.java (4. versija)

importēt java.util.function.Supplier; public class MRDemo {public static void main (String [] args) {Piegādātāja piegādātājs = MRDemo :: new; System.out.println (piegādātājs.get ()); }}

Uzskaita 4 MRDemo :: jauns konstruktora atsauce ir līdzvērtīga lambda () -> jauns MRDemo (). Izteiksme piegādātājs.get () izpilda šo lambda, kas izsauc MRDemonoklusējuma konstruktors bez argumentiem un atgriež MRDemo objekts, kas tiek nodots System.out.println (). Šī metode pārveido objektu par virkni, kuru tas izdrukā.

Tagad pieņemsim, ka jums ir klase ar konstruktoru bez argumentiem un konstruktors, kurš ņem argumentu, un jūs vēlaties izsaukt konstruktoru, kurš ņem argumentu. Šo uzdevumu varat paveikt, izvēloties citu funkcionālo saskarni, piemēram, iepriekš definēto Funkcija saskarne parādīta 5. sarakstā.

5. saraksts. MRDemo.java (5. versija)

importēt java.util.function.Function; public class MRDemo {private String name; MRDemo () {name = ""; } MRDemo (virknes nosaukums) {this.name = nosaukums; System.out.printf ("MRDemo (virknes nosaukums) izsaukts ar% s% n", nosaukums); } public static void main (String [] args) {Funkcijas funkcija = MRDemo :: new; System.out.println (function.apply ("kāds nosaukums")); }}

Funkcijas funkcija = MRDemo :: new; liek kompilatoram meklēt konstruktoru, kas ņem a Stīga arguments, jo Funkcija's pieteikties () metode prasa vienu (šajā kontekstā) Stīga arguments. Izpilda function.apply ("kāds nosaukums") rezultātā "kāds vārds" tiek nodota MRDemo (virknes nosaukums).

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