Methodeverwijzingen in Java

1. Overzicht

Een van de meest welkome veranderingen in Java 8 was de introductie van lambda-expressies, omdat deze ons in staat stellen af ​​te zien van anonieme klassen, waardoor de standaardcode aanzienlijk wordt verminderd en de leesbaarheid wordt verbeterd.

Methodeverwijzingen zijn een speciaal type lambda-uitdrukkingen. Ze worden vaak gebruikt om eenvoudige lambda-expressies te maken door te verwijzen naar bestaande methoden.

Er zijn vier soorten methodeverwijzingen:

  • Statische methoden
  • Instantiemethoden van bepaalde objecten
  • Instantiemethoden van een willekeurig object van een bepaald type
  • Constructor

In deze zelfstudie verkennen we methodeverwijzingen in Java.

2. Verwijzing naar een statische methode

We beginnen met een heel eenvoudig voorbeeld, met hoofdletters en een lijst met Snaren:

Lijst berichten = Arrays.asList ("hallo", "baeldung", "lezers!");

We kunnen dit bereiken door gebruik te maken van een eenvoudige lambda-uitdrukking die de StringUtils.capitalize () methode direct:

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

Of we kunnen een methodeverwijzing gebruiken om eenvoudig naar de kapitaliseren statische methode:

messages.forEach (StringUtils :: capitalize);

Merk op dat methodeverwijzingen altijd de :: operator.

3. Verwijzing naar een instantiemethode van een bepaald object

Laten we twee klassen beschouwen om dit type methodeverwijzing te demonstreren:

openbare klasse Bicycle {private String brand; privé Geheel getal frameSize; // standard constructor, getters and setters} public class BicycleComparator implementeert Comparator {@Override public int Compare (Bicycle a, Bicycle b) {return a.getFrameSize (). CompareTo (b.getFrameSize ()); }}

En laten we een Fietsvergelijker object om fietsframematen te vergelijken:

BicycleComparator bikeFrameSizeComparator = nieuwe BicycleComparator ();

We zouden een lambda-uitdrukking kunnen gebruiken om fietsen op framemaat te sorteren, maar we zouden ter vergelijking twee fietsen moeten specificeren:

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

In plaats daarvan kunnen we een methodeverwijzing gebruiken om de compiler-afhandelingsparameter voor ons door te geven:

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

De methodeverwijzing is veel schoner en beter leesbaar, omdat onze bedoeling duidelijk wordt weergegeven door de code.

4. Verwijzing naar een instantiemethode van een willekeurig object van een bepaald type

Dit type methodeverwijzing is vergelijkbaar met het vorige voorbeeld, maar zonder dat u een aangepast object hoeft te maken om de vergelijking uit te voeren.

Laten we een Geheel getal lijst die we willen sorteren:

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

Als we een klassieke lambda-uitdrukking gebruiken, moeten beide parameters expliciet worden doorgegeven, terwijl het gebruik van een methodeverwijzing veel eenvoudiger is:

numbers.stream () .sorted ((a, b) -> a.compareTo (b)); numbers.stream () .sorted (Integer :: CompareTo);

Hoewel het nog steeds een oneliner is, is de referentiemethode veel gemakkelijker te lezen en te begrijpen.

5. Verwijzing naar een constructor

We kunnen op dezelfde manier naar een constructor verwijzen als in ons eerste voorbeeld naar een statische methode. Het enige verschil is dat we de nieuw trefwoord.

Laten we een Fiets array uit een Draad lijst met verschillende merken:

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

Eerst voegen we een nieuwe constructor toe aan onze Fiets klasse:

openbare fiets (merk String) {this.brand = merk; this.frameSize = 0; } 

Vervolgens gebruiken we onze nieuwe constructor van een methodeverwijzing en maken we een Fiets array van het origineel Draad lijst:

bikeBrands.stream () .map (Fiets :: nieuw) .toArray (Fiets [] :: nieuw); 

Merk op hoe we beide hebben gebeld Fiets en Array constructeurs die een methodeverwijzing gebruiken, waardoor onze code een veel beknopter en duidelijker uiterlijk krijgt.

6. Aanvullende voorbeelden en beperkingen

Zoals we tot nu toe hebben gezien, zijn methodeverwijzingen een uitstekende manier om onze code en intenties heel duidelijk en leesbaar te maken. We kunnen ze echter niet gebruiken om allerlei lambda-expressies te vervangen, omdat ze enkele beperkingen hebben.

Hun belangrijkste beperking is het resultaat van wat ook hun grootste kracht is: de uitvoer van de vorige uitdrukking moet overeenkomen met de invoerparameters van de handtekening van de methode waarnaar wordt verwezen.

Laten we een voorbeeld van deze beperking bekijken:

createBicyclesList (). forEach (b -> System.out.printf ("Fietsmerk is '% s' en framemaat is '% d'% n", b.getBrand (), b.getFrameSize ()));

Dit eenvoudige geval kan niet worden uitgedrukt met een methodeverwijzing, omdat de printf methode vereist 3 parameters in ons geval, en gebruiken createBicyclesList (). forEach () zou alleen toestaan ​​dat de methodeverwijzing één parameter afleidt (het Fiets voorwerp).

Laten we tot slot eens kijken hoe we een functie zonder bewerking kunnen maken waarnaar kan worden verwezen vanuit een lambda-expressie.

In dit geval willen we een lambda-expressie gebruiken zonder de bijbehorende parameters te gebruiken.

Laten we eerst het doNothingAtAll methode:

privé statische leegte doNothingAtAll (Object ... o) {}

Omdat het een varargs-methode is, werkt het in elke lambda-expressie, ongeacht het object waarnaar wordt verwezen of het aantal afgeleide parameters.

Laten we het nu in actie zien:

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

7. Conclusie

In deze korte tutorial hebben we geleerd welke methodeverwijzingen in Java zijn en hoe we deze kunnen gebruiken om lambda-expressies te vervangen, waardoor de leesbaarheid wordt verbeterd en de bedoeling van de programmeur wordt verduidelijkt.

Alle code die in dit artikel wordt gepresenteerd, is beschikbaar op GitHub.