Metodehenvisninger i Java

1. Oversigt

En af de mest velkomne ændringer i Java 8 var introduktionen af ​​lambda-udtryk, da disse giver os mulighed for at give afkald på anonyme klasser, hvilket i høj grad reducerer kedelpladekoden og forbedrer læsbarheden.

Metodehenvisninger er en særlig type lambda-udtryk. De bruges ofte til at skabe enkle lambda-udtryk ved at henvise til eksisterende metoder.

Der er fire slags metodereferencer:

  • Statiske metoder
  • Instansmetoder for bestemte objekter
  • Instansmetoder for et vilkårligt objekt af en bestemt type
  • Konstruktør

I denne vejledning udforsker vi metodereferencer i Java.

2. Henvisning til en statisk metode

Vi begynder med et meget simpelt eksempel, der kapitaliserer og udskriver en liste over Strenge:

Listebeskeder = Arrays.asList ("hej", "baeldung", "læsere!");

Vi kan opnå dette ved at udnytte et enkelt lambda-udtryk, der kalder StringUtils.capitalize () metode direkte:

messages.forEach (word -> StringUtils.capitalize (word));

Eller vi kan bruge en metodehenvisning til blot at henvise til kapitalisere statisk metode:

messages.forEach (StringUtils :: kapitaliser)

Bemærk, at metodereferencer altid bruger :: operatør.

3. Henvisning til en instansmetode for et bestemt objekt

For at demonstrere denne type metodehenvisning, lad os overveje to klasser:

offentlig klasse Cykel {private String brand; privat heltal rammeSize; // standardkonstruktør, getters og setter} public class BicycleComparator implementerer Comparator {@Override public int compare (Bicycle a, Bicycle b) {return a.getFrameSize (). comparTo (b.getFrameSize ()); }}

Og lad os oprette en BicycleComparator modstand mod at sammenligne cykelstelstørrelser:

BicycleComparator bikeFrameSizeComparator = ny BicycleComparator ();

Vi kunne bruge et lambda-udtryk til at sortere cykler efter rammestørrelse, men vi skulle specificere to cykler til sammenligning:

createBicyclesList (). stream () .sorted ((a, b) -> bikeFrameSizeComparator.compare (a, b));

I stedet kan vi bruge en metodehenvisning til at få compilerhåndteringsparameteren til os:

createBicyclesList (). stream () .sorted (bikeFrameSizeComparator :: sammenlign);

Metodehenvisningen er meget renere og mere læselig, da vores hensigt tydeligt fremgår af koden.

4. Henvisning til en instansmetode for et vilkårligt objekt af en bestemt type

Denne type metodehenvisning svarer til det foregående eksempel, men uden at skulle oprette et brugerdefineret objekt for at udføre sammenligningen.

Lad os oprette en Heltal liste, som vi vil sortere:

Listenumre = Arrays.asList (5, 3, 50, 24, 40, 2, 9, 18);

Hvis vi bruger et klassisk lambda-udtryk, skal begge parametre overføres eksplicit, mens brug af en metodehenvisning er meget mere ligetil:

numbers.stream () .sorted ((a, b) -> a.compareTo (b)); numbers.stream () .sorted (Heltal :: sammenlignTo);

Selvom det stadig er en linie, er metodereferencen meget lettere at læse og forstå.

5. Henvisning til en konstruktør

Vi kan henvise til en konstruktør på samme måde, som vi refererede til en statisk metode i vores første eksempel. Den eneste forskel er, at vi bruger ny nøgleord.

Lad os oprette en Cykel array ud af en Snor liste med forskellige mærker:

Liste over bikeBrands = Arrays.asList ("Giant", "Scott", "Trek", "GT");

Først tilføjer vi en ny konstruktør til vores Cykel klasse:

offentlig cykel (String brand) {this.brand = brand; this.frameSize = 0; } 

Dernæst bruger vi vores nye konstruktør fra en metodehenvisning og laver en Cykel array fra originalen Snor liste:

bikeBrands.stream () .map (Cykel :: ny) .toArray (Cykel [] :: ny); 

Læg mærke til, hvordan vi kaldte begge dele Cykel og Array konstruktører ved hjælp af en metodereference, der giver vores kode et meget mere kortfattet og tydeligt udseende.

6. Yderligere eksempler og begrænsninger

Som vi hidtil har set, er metodereferencer en fantastisk måde at gøre vores kode og intentioner meget klare og læselige. Vi kan dog ikke bruge dem til at erstatte alle slags lambda-udtryk, da de har nogle begrænsninger.

Deres vigtigste begrænsning er et resultat af, hvad der også er deres største styrke: output fra det tidligere udtryk skal matche inputparametrene for den refererede metodesignatur.

Lad os se et eksempel på denne begrænsning:

createBicyclesList (). forEach (b -> System.out.printf ("Cykelmærke er '% s' og rammestørrelse er '% d'% n", b.getBrand (), b.getFrameSize ()));

Denne enkle sag kan ikke udtrykkes med en metodehenvisning, fordi printf metode kræver 3 parametre i vores tilfælde og brug createBicyclesList (). forEach () tillader kun, at metoden henviser til at udlede en parameter ( Cykel objekt).

Lad os endelig undersøge, hvordan man opretter en funktion uden funktionsmåde, der kan refereres til fra et lambda-udtryk.

I dette tilfælde vil vi bruge et lambda-udtryk uden at bruge dets parametre.

Lad os først oprette gør intetAtAll metode:

privat statisk ugyldighed doNothingAtAll (Objekt ... o) {}

Da det er en varargs-metode, fungerer den i ethvert lambda-udtryk, uanset det refererede objekt eller antallet af afledte parametre.

Lad os nu se det i aktion:

createBicyclesList () .forEach ((o) -> MethodReferenceExamples.doNothingAtAll (o)); 

7. Konklusion

I denne hurtige vejledning lærte vi, hvilke metodereferencer der er i Java, og hvordan man bruger dem til at erstatte lambda-udtryk, hvilket forbedrer læsbarheden og tydeliggør programmørens hensigt.

Al kode præsenteret i denne artikel er tilgængelig på GitHub.