De dubbele dubbele punt-operator in Java 8

1. Overzicht

In dit korte artikel bespreken we de dubbele dubbele punt operator ( :: ) in Java 8 en bespreek de scenario's waarin de operator kan worden gebruikt.

2. Van Lambdas naar Double Colon Operator

Met Lambdas-expressies hebben we gezien dat code erg beknopt kan worden.

Bijvoorbeeld naar maak een vergelijker, de volgende syntaxis is voldoende:

Comparator c = (Computer c1, Computer c2) -> c1.getAge (). CompareTo (c2.getAge ()); 

Vervolgens, met type-gevolgtrekking:

Comparator c = (c1, c2) -> c1.getAge (). CompareTo (c2.getAge ());

Maar kunnen we bovenstaande code nog expressiever en leesbaarder maken? Laten we eens kijken:

Comparator c = Comparator.comparing (Computer :: getAge); 

We hebben de :: operator als afkorting voor lambda's die een specifieke methode aanroepen - op naam. En het eindresultaat is natuurlijk een nog beter leesbare syntaxis.

3. Hoe werkt het?

Heel eenvoudig gezegd: als we een methodeverwijzing gebruiken, wordt de doelverwijzing voor het scheidingsteken geplaatst :: en de naam van de methode staat erachter.

Bijvoorbeeld:

Computer :: getAge;

We kijken naar een methodeverwijzing naar de methode getAge gedefinieerd in de Computer klasse.

We kunnen dan met die functie werken:

Functie getAge = Computer :: getAge; Geheel getal computerAge = getAge.apply (c1); 

Merk op dat we naar de functie verwijzen - en deze vervolgens toepassen op het juiste soort argument.

4. Verwijzingen naar methoden

In heel wat scenario's kunnen we deze operator goed gebruiken.

4.1. Een statische methode

Ten eerste gaan we er gebruik van maken een statische hulpprogramma-methode:

Lijstinventaris = Arrays.asList (nieuwe computer (2015, "wit", 35), nieuwe computer (2009, "zwart", 65)); inventaris.forEach (ComputerUtils :: reparatie); 

4.2. Een instantiemethode van een bestaand object

Laten we vervolgens een interessant scenario bekijken - verwijzend naar een methode van een bestaande objectinstantie.

We gaan de variabele gebruiken Systeem.uit - een object van type PrintStream die de afdrukken methode:

Computer c1 = nieuwe computer (2015, "wit"); Computer c2 = nieuwe computer (2009, "zwart"); Computer c3 = nieuwe computer (2014, "zwart"); Arrays.asList (c1, c2, c3) .forEach (System.out :: print); 

4.3. Een instantiemethode van een willekeurig object van een bepaald type

Computer c1 = nieuwe computer (2015, "wit", 100); Computer c2 = nieuwe MacbookPro (2009, "zwart", 100); Lijst inventaris = Arrays.asList (c1, c2); inventaris.forEach (Computer :: turnOnPc); 

Zoals u kunt zien, verwijzen we naar de turnOnPc methode niet op een specifiek exemplaar, maar op het type zelf.

Op regel 4 de instantiemethode turnOnPc zal worden opgeroepen voor elk object van voorraad.

En dit betekent natuurlijk dat - voor c1 de methode turnOnPc zal worden gebeld op de Computer instantie en voor c2 Aan MacbookPro voorbeeld.

4.4. Een supermethode van een bepaald object

Stel dat je de volgende methode hebt in het Computer superklasse:

publiek Double berekenValue (Double initialValue) {return initialValue / 1.50; } 

en deze in MacbookPro subklasse:

@Override public Double berekenValue (Double initialValue) {Functie function = super :: berekenValue; Dubbele pcValue = function.apply (initialValue); retourneer pcValue + (initialValue / 10); } 

Een telefoontje naar berekenwaarde methode op een MacbookPro voorbeeld:

macbookPro.calculateValue (999,99); 

zal ook een oproep produceren naar berekenwaarde op de Computer superklasse.

5. Referenties voor constructeurs

5.1. Maak een nieuwe instantie

Verwijzen naar een constructor om een ​​object te instantiëren, kan vrij eenvoudig zijn:

@FunctionalInterface openbare interface InterfaceComputer {Computer create (); } InterfaceComputer c = Computer :: nieuw; Computercomputer = c.create (); 

Wat als u twee parameters heeft in een constructor?

BiFunction c4Function = Computer :: nieuw; Computer c4 = c4Function.apply (2013, "wit"); 

Als de parameters drie of meer zijn, moet u een nieuwe functionele interface definiëren:

@FunctionalInterface-interface TriFunction {R van toepassing (A a, B b, C c); standaard TriFunction andThen (Functie na) {Objects.requireNonNull (na); return (A a, B b, C c) -> after.apply (pas toe (a, b, c)); }} 

Initialiseer vervolgens uw object:

TriFunction c6Function = Computer :: nieuw; Computer c3 = c6Function.apply (2008, "zwart", 90); 

5.2. Maak een array

Laten we tot slot kijken hoe we een array van Computer objecten met vijf elementen:

Functie computerCreator = Computer [] :: nieuw; Computer [] computerArray = computerCreator.apply (5); 

6. Conclusie

Zoals we beginnen te zien, zal de dubbele dubbele punt-operator - geïntroduceerd in Java 8 - erg handig zijn in sommige scenario's, en vooral in combinatie met Streams.

Het is ook heel belangrijk om naar functionele interfaces te kijken voor een beter begrip van wat er achter de schermen gebeurt.

Het complete broncode want het voorbeeld is beschikbaar in dit GitHub-project - dit is een Maven- en Eclipse-project, zodat het kan worden geïmporteerd en gebruikt zoals het is.