Modificări în Java limbă 8

expresii lambda și modificări în clasa de interfață nu Java 8 limbaj nou

Java ™ versiunea 8 include noi caracteristici importante de limbă care oferă dezvoltatorilor modalități mai ușoare de a construi programe. T. N. expresii Lambda (expresie lamba) definesc o nouă sintaxă pentru blocurile încorporate de cod, care oferă aceeași flexibilitate ca și clase interioare anonime, dar cu un număr redus semnificativ de template-uri (boilerplate). Modificări în zona de interfață vă permite să le adăugați la interfața existente, fără a sacrifica compatibilitatea cu codul existent. Aflați modul în care aceste schimbări să lucreze împreună, precum și citi articolul 8 însoțitoare Java de bază concurenta. care descrie utilizarea expresiilor lambda cu m. n. Java 8 fluxuri (flux).

Denis Sosnoski. Consultant, Sosnoski Software Solutions, Inc.

Denis Sosnoski (Dennis Sosnoski) - fondator si plumb Java specialist tehnologie companie de consultanță - Sosnoski Software Solutions, Inc. specializata in training si consultanta pe probleme de XML și servicii web. El are mai mult de 30 de ani de experiență în dezvoltarea de software profesional, specializat în XML server-side și Java-tehnologie. Dennis este dezvoltatorul principal al open source JiBX XML de date obligatorii. construit pe baza tehnologiei Java clasă și legate de JibxSoap-cadru de servicii web. precum Apache Axis2-cadru de servicii web. El a fost, de asemenea, unul dintre expert în dezvoltarea de 2.0 caietul de sarcini JAX-WS.

Cea mai mare schimbare în Java 8 - este adăugarea de suport pentru așa-numitul .. expresii lambda. expresii Lambda sunt blocuri de cod care pot fi transmise prin referință. Acestea sunt similare cu dispozitive de închidere (închidere), în unele alte limbaje de programare: codul care implementează funcția acceptă în mod opțional unul sau mai mulți parametri de intrare și, opțional, returnează valoarea rezultatului. Închiderile sunt definite în contextul, și să aibă acces (în cazul expresiilor lambda - acces numai de citire) la valorile în acest context.

Dacă nu sunteți familiarizat cu sistem de închidere, e în regulă. In Java 8 Lambda - este de fapt specializare clase interioare anonime, care marchează aproape fiecare Java Developer. Anonim clasele interne de punere în aplicare oferă built-in a interfetei sau subclase clasa de bază pe care doriți să utilizați doar un singur punct de cod de program. expresii Lambda sunt folosite în același mod, dar cu sintaxa abreviată, ceea ce le face mai compact decât o definiție standard a clasei interioare.

În acest articol, veți vedea cum să folosească expresii lambda în situații diferite, și să învețe despre asociate definiție extins limbajul de interfață Java. În articolul 8 însoțitoare Elementele de bază Java JVM de concurenta ciclu oferă exemple concurrency suplimentare de expresii cum lambda, inclusiv utilizarea lor combinată cu t. N. Java 8 fluxuri (flux).

Conceptul de expresii lambda

Expresia Lambda este întotdeauna realizarea că în Java 8 terminologia este numită interfața funcțională. interfață de clasă. definește o singură metodă abstractă. Restricțiile de utilizare a nu mai mult de o metodă abstractă este importantă, deoarece sintaxa expresie lambda nu utilizează numele metodei. In schimb, expresia folosește t. N. dactilografiere rață (rață tastare - potrivirea cu tipurile de parametri și valoarea de întoarcere, așa cum se face în mai multe limbi dinamice) pentru a se asigura că furnizarea unei expresii lambda este în concordanță cu metoda de interfață așteptată.

Listarea 1. Compararea și clasa interioară Lambda anonimă

Listarea expresie 1 lambda este utilizată ca înlocuitor pentru clasele interne anonime convenționale. Acest tip de o clasă internă convențională este foarte frecventă în practică, astfel încât expresii lambda oferi instant câștigătoare programatori Java la 8 (în acest caz, pentru a efectua lucrările în comparație, și clasele interne, și expresia lambda utilizează metoda implementată în clasa Name. În cazul în care codul metodă compareTo () a fost inserată în expresia lambda, expresia este mai concisă).

interfețe funcționale standard

  • Funcția: Acceptă un singur argument, returnează un rezultat bazat pe valoarea parametrului.
  • Predicatului: Acceptă un singur argument, returnează un rezultat boolean bazat pe valoarea parametrului.
  • Bifunctiei: ia doi parametri, returnează un rezultat pe baza valorii parametrului.
  • Furnizor: nu prezintă parametri, returnează rezultatul.
  • Consumatorilor: acceptă un singur argument, returnează rezultatul (void)
Listarea 2. Combinația predicatelor

În Listarea 2, codul definește două tipuri de predicatului constructii. din care una corespunde numelui Sally. iar a doua corespunde numelor coadă. numesc pred1.or (pred2) Metoda creează un predicat combinat definit prin aplicarea acestor două predicate în ordine, cu valoarea returnată a true. în cazul în care oricare dintre aceste două predicate este setat true (de ieșire de la începutul anului ca și în cazul unui operator logic || în Java). List.removeIf () metodă utilizează predicatul combinate pentru a șterge numele corespunzătoare din listă.

În Java 8 definește multe combinații interfețe utile java.util.function dar aceste combinații nu sunt coerente. Toate variantele de predicatului (DoublePredicate. IntPredicate. LongPredicate și predicatului ) Definiți aceleași tehnici pentru combinații și modificări: și (). nega (). sau (). Cu toate acestea, variațiile primitivelor Funcție Metodele nu determină combinarea și modificarea. Dacă aveți experiență cu limbaje de programare funcționale, atunci s-ar putea găsi aceste diferențe și omisiuni redundante.

Modificări în clasele de interfață

Schimbată structura 8 interfață Java clasă (cum ar fi Comparator. Utilizat în exemplul 1), în parte pentru a simplifica utilizarea expresiilor lambda. Versiunile anterioare ale Java 8 interfață permite să se determine numai constante și metode abstracte, pe care le-ați avut apoi să pună în aplicare. În Java 8 adaugă capacitatea de a defini interfețe în metoda statică și implicit -methods. Statică metode în interfața - este, în esență, la fel ca și electricitatea statică metodele din clasa abstractă. Default-metode sunt mai mult ca metodele de interfață în stil vechi, dar acestea au oferit o implementare care este utilizat în cazul în care dezvoltatorul nu suprascrie implicit-metoda.

O caracteristică importantă a metodelor implicite este faptul că acestea pot fi adăugate la o interfață de clasă existente, fără a sacrifica compatibilitatea cu alt cod care utilizează această interfață (cu condiția ca codul existent nu utilizează același nume de metodă pentru orice alt scop) . Aceasta este o caracteristică foarte puternic; designeri Java8-l la „reglajul fin“ expresiile suport lambda utilizat pentru mai multe existente în Java-biblioteci. Listarea 3 prezintă un exemplu corespunzător - sub forma unei a treia metodă de sortare a numelor adăugate la codul din Listarea 1.

Listarea 3. Legarea în lanțul comparatoare pe baza expresiilor cheie-extractor

Codul din listingul 3 prezintă o primă aplicare a noii metode, statică-Comparator.comparing () pentru a crea un comparator bazat pe o cheie de extracție din Lambda definit-dezvoltator (în sens tehnic lambda-cheie de extracție este o instanță a interfeței java.util.function.Function. în cazul în care tipul de rezultatul comparator compatibil pentru Atribuit T. și tipul cheii R extras implementeaza interfata Comparabil). Acest cod demonstrează, de asemenea, asocierea comparatori cu noul Comparator.thenComparing default-metoda (). că, în Listarea 3 returnează un nou comparator pentru a sorta mai întâi după nume și apoi după nume.

S-ar putea avea impresia că posibilitatea de a introduce următorul comparator de proiectare:

Din păcate, acest design nu funcționează cu o interfață, cum ar fi Java 8. Trebuie să furnizați compilatorului mai multe informații despre electricitatea statică metoda de așteptat tip de rezultat - folosind oricare dintre următoarele forme:

Prima formă adaugă un tip de parametru lambda la expresia lambda: (Name name1) -> name1.lastName. Cu ajutorul compilatorului este capabil să înțeleagă restul de ceea ce trebuie să facă. A doua formă a tipurilor de compilator T și R pentru interfața funcțională (care în acest caz este implementat folosind transferate) Lambda comparând metoda ().

Capacitatea de a proiecta cu ușurință comparatoare, și să le legați într-un lanț - aceasta este o caracteristică foarte utilă de Java 8, dar se realizează la costul de a crește și mai mult nivelul de dificultate. În Java 7 interfață Comparator definește două metode (Metoda compara () și egali omniprezente () metoda. Care este garantat este definit pentru fiecare obiect). Java Versiunea 8 specifică 18 metode (două metode originale, plus 9 noi statice-metode și 7 noi default-Method). Veți găsi că acest model este o inflație interfețe pe scară largă pentru lucrul cu expresii lambda repetate într-o mare parte din Java standard bibliotecă.

Utilizarea metodelor existente ca expresii lambda

Listarea 4. Folosind metodele existente ca expresii lambda

Codul din listingul 4 face același lucru, că codul din listingul 3, dar folosind metode existente. Puteți utiliza Java existente 8 în sintaxa referiri la o metodă ClassName :: METHODNAME. de a utiliza orice metodă, în același mod ca și când ar fi o expresie lambda. Rezultatul va fi exact la fel ca și în cazul determinării expresiei lambda, care invocă această metodă. Puteți utiliza linkurile din metoda de electricitatea statică metode, de exemplu-metodele oricărui obiect particular sau ca un tip de intrare pentru expresii lambda (așa cum se arată în Listing 4. unde getFirstName () și getLastName () - este metodele de tip instanță de comparat Nume), și pentru designeri.

Pentru a depăși limitările de tipul de „finală în mod eficient“, poate fi folosit unele metode de depanare. De exemplu, pentru a folosi numai valorile curente ale anumitor variabile în expresia lambda, puteți adăuga o nouă metodă, care ia valorile ca parametri și returnează o expresie lambda (sub forma unor trimiteri adecvate la interfața) cu valorile capturate (Capturat). Dacă doriți să modificați valoarea lambda din contextul din jur, puteți încadra valoarea corespunzătoare sub formă de a permite modificări ale titularului (titular).

Expresia Lambda - ceea ce se întâmplă în spatele scenei

expresii Lambda sunt foarte asemănătoare cu clasele interne anonime, dar puse în aplicare în mod diferit. Java-clase interne - este un design voluminos; ele se extind până la nivelul de bytecode, și pentru fiecare clasă de interior există un fișier de clasă separată. O mare parte a datelor este duplicat (în principal, sub formă de intrări constante piscină), și clasa de încărcare adaugă costuri semnificative la stadiul de execuție - toate ca rezultat al adăugării unei cantități mici de cod.

În loc de a folosi expresii lambda o versiune separată fișier de clasă pentru Java 8 se bazează pe invokedynamic bytecode-instrucțiuni. Adăugat în versiunea Java 7. Instrucțiuni invokedynamic axat pe metoda bootstrap, care, la rândul său, creează realizarea lambda expresii primul apel la această metodă. După aceea, provocarea imediată a punerii în aplicare a returnare. Acest lucru evită aeriene de spațiu consumat de către un fișier separat pentru fiecare clasă, și o mare parte din costurile de faza de execuție, determină clasa de încărcare. În același mod de realizare a funcției lambda este amânată până în momentul bootstrap. Bootstrap-cod generat in prezent Java 8, colectează în etapa de execuție a unei noi clase de expresie lambda, dar implementările viitoare pot fi bine utilizate de către alte abordări.

Java Versiunea 8 include instrumente de optimizare care fac realizarea de expresii lambda prin instrucțiuni invokedynamic funcționează bine din punct de vedere practic. Majoritatea celorlalte JVM-limbi, inclusiv Scala (2.10.x), utilizează clasele interne generate de compilator pentru închideri. Versiunile viitoare ale acestor limbi, probabil, se va trece la o abordare bazată pe un invokedynamic de instrucțiuni pentru instrumente de optimizare utilizare oferite de versiunea Java 8 (și versiunile ulterioare).

Restricții expresii lambda

Așa cum am menționat mai devreme în acest articol, expresii lambda sunt întotdeauna implementări ale unui anumit interfață funcțională. expresii Lambda pot fi transmise numai ca o referință la interfața; ca și în cazul altor implementări ale interfeței, lambda expresie numai ca o interfață specifică poate fi utilizată, pentru care a fost creat. Codul din Listarea 5 arată o pereche de restricție identice (cu excepția numelor) interfețe funcționale. 8 compilatorul Java adoptă metoda de String :: lungime lambda-realizare ambele interfețe. Cu toate acestea, odată ce expresia lambda este definită ca un exemplu de prima interfață, ea nu mai poate fi folosit ca un al doilea exemplu de interfață.

Listarea 5. Restricții expresii lambda

Codul din listingul 5 nu este o surpriza pentru oricine care crede în ceea ce privește Java-interfață, deoarece a lucrat întotdeauna acest mod interfețe Java- (cu excepția unui lucru - o referire la metodele care au apărut în versiunea de Java 8). Cu toate acestea, dezvoltatorii care au lucrat cu limbaje de programare funcționale, cum ar fi Scala lui, poate considera ca o interfață limitată nu este foarte clar la nivel intuitiv.

În limbaje de programare funcționale sunt utilizate pentru a determina variabilele nu sunt interfețe și tipuri de funcții. Banal pentru limbi este de a lucra cu t. N. Funcții de ordin mai mare - sunt funcții care transmit funcții ca parametri sau valori funcție de întoarcere ca. Rezultatul este un stil de programare mult mai flexibilă decât în ​​cazul expresiilor lambda, inclusiv capacitatea de a utiliza funcții ca și construirea de blocuri pentru prepararea altor funcții. Java versiunea 8 nu specifică tipurile de funcții, astfel încât să nu poate fi expresii lambda în acest fel. Ați putea fi interfețe (a se vedea. Listarea 3), dar numai cu cod scris pentru a lucra cu interfețe specifice implicate. Într-o nouă interfață java.util.function doar 43 de pachete configurat în mod special pentru utilizarea cu expresii lambda. Având în vedere sutele de interfețe existente, se poate spune că lista de moduri în care puteți face interfețe va fi întotdeauna strict limitată.

Optarea pentru utilizarea în loc de a adăuga interfețe pentru tipuri Java de funcții a fost în mod deliberat. Aceasta elimină necesitatea de a face modificări semnificative ale Java-biblioteci, și permite utilizarea expresiilor lambda cu bibliotecile existente. Dezavantajul acestei abordări este că limitează Java 8 așa-numita „interfață de programare“ sau programare funcțional similare - în loc de adevărată programare funcțională. Cu toate acestea, prezența unui număr mare de alte limbi sunt disponibile pe platforma JVM (inclusiv funcțională), slăbește în mod semnificativ această limitare.

concluzie

expresii Lambda sunt o expansiune foarte semnificativă a limbajului Java. Ca și alte expansiune la fel de semnificativ - o trimitere la metodele - acestea vor deveni rapid un instrument indispensabil pentru toate Java-developers - ca transfer de aplicații pe platforma Java 8. expresii Lambda sunt utile în special în legătură cu așa-numitele .. Java 8 fluxuri (flux). Articolul a JVM simultaneitatea: Elementele de bază Java 8 prezinta concurenta schimbul de expresii lambda și fluxuri pentru a simplifica programarea paralelă și de a îmbunătăți performanța de aplicare.

Obțineți produse și tehnologii

  • Alăturați-vă comunității developerWorks. Conectează-te cu alți utilizatori developerWorks și face cunoștință cu orientate spre dezvoltator forumuri, bloguri, grupuri și resurse wiki-urile.

articole similare