Gegeneraliseerde inferentie van het doeltype in Java

1. Inleiding

Type Inference werd geïntroduceerd in Java 5 als aanvulling op de introductie van generieke geneesmiddelen en werd aanzienlijk uitgebreid in de volgende Java-releases, ook wel Generalized Target-Type Inference genoemd.

In deze zelfstudie verkennen we dit concept met codevoorbeelden.

2. Generiek

Generics hebben ons veel voordelen opgeleverd, zoals verhoogde typeveiligheid, het vermijden van typefouten en generieke algoritmen. In dit artikel leest u meer over generieke geneesmiddelen.

De introductie van Generics resulteerde in de noodzaak om boilerplate-code te schrijven vanwege de noodzaak om typeparameters door te geven. Enkele voorbeelden zijn:

Kaart mapOfMaps = nieuwe HashMap(); Lijst strList = Collections.emptyList (); List intList = Collections.emptyList ();

3. Typ Inference Before Java 8

Om de onnodige breedsprakigheid van de code te verminderen, is Type Inference geïntroduceerd in Java, dat is het proces waarbij niet-gespecificeerde gegevenstypen van een uitdrukking automatisch worden afgeleid op basis van de contextuele informatie.

Nu kunnen we dezelfde generieke typen en methoden aanroepen zonder de parametertypen op te geven. De compiler leidt automatisch de parametertypes af als dat nodig is.

We kunnen dezelfde code zien met behulp van het nieuwe concept:

Lijst strListInferred = Collections.emptyList (); List intListInferred = Collections.emptyList (); 

In het bovenstaande voorbeeld op basis van de verwachte retourtypen Lijst en Lijst, kan de compiler de parameter type afleiden naar de volgende generieke methode:

openbare statische definitieve lijst emptyList () 

Zoals we kunnen zien, is de resulterende code beknopt. Nu kunnen we generieke methoden als een gewone methode aanroepen als de parameter type kan worden afgeleid.

In Java 5 zouden we Type-Inference in specifieke contexten kunnen doen, zoals hierboven weergegeven.

Java 7 breidde de contexten uit waarin het kon worden uitgevoerd. Het introduceerde de diamantoperator . In dit artikel leest u meer over de diamantoperator.

Nu, we kunnen deze bewerking uitvoeren voor generieke klasseconstructors in een toewijzingscontext. Een voorbeeld hiervan is:

Kaart mapOfMapsInferred = nieuwe HashMap ();

Hier gebruikt de Java-compiler het verwachte toewijzingstype om de typeparameters naar af te leiden Hash kaart constructeur.

4. Gegeneraliseerde inferentie van doeltype - Java 8

Java 8 heeft de reikwijdte van Type Inference verder uitgebreid. We noemen deze uitgebreide inferentiemogelijkheid Generalized Target-Type Inference. U kunt hier de technische details lezen.

Java 8 introduceerde ook Lambda Expressions. Lambda-expressies hebben geen expliciet type. Hun type wordt afgeleid door te kijken naar het doeltype van de context of situatie. Het doeltype van een uitdrukking is het gegevenstype dat de Java-compiler verwacht, afhankelijk van waar de uitdrukking wordt weergegeven.

Java 8 ondersteunt inferentie met behulp van Target-Type in een methodecontext. Wanneer we een generieke methode aanroepen zonder expliciete type-argumenten, kan de compiler kijken naar de methode-aanroep en de bijbehorende methode-declaraties om het type-argument (of de argumenten) te bepalen die de aanroep toepasbaar maken.

Laten we een voorbeeldcode bekijken:

static List add (List list, T a, T b) {list.add (a); lijst.add (b); retourlijst; } Lijst strListGeneralized = add (new ArrayList (), "abc", "def"); Lijst intListGeneralized = add (new ArrayList (), 1, 2); Lijst numListGeneralized = add (new ArrayList (), 1, 2.0);

In de code, ArrayList geeft niet expliciet het type-argument. Dus de compiler moet het afleiden. Eerst kijkt de compiler naar de argumenten van de add-methode. Vervolgens wordt gekeken naar de parameters die bij verschillende aanroepen worden doorgegeven.

Het presteert inferentie van toepassing op aanroep analyse om te bepalen of de methode van toepassing is op deze aanroepen. Als er meerdere methoden van toepassing zijn vanwege overbelasting, zou de compiler de meest specifieke methode kiezen.

Dan, de compiler presteert aanroepingstype gevolgtrekking analyse om de type-argumenten te bepalen.In deze analyse worden ook de verwachte doeltypes gebruikt. Het leidt de argumenten in de drie gevallen af ​​als ArrayList, ArrayList en ArrayList.

Inferentie met doeltype stelt ons in staat om geen typen op te geven voor lambda-expressieparameters:

Lijst intList = Arrays.asList (5, 2, 4, 2, 1); Collections.sort (intList, (a, b) -> a.compareTo (b)); List strList = Arrays.asList ("Rood", "Blauw", "Groen"); Collections.sort (strList, (a, b) -> a.compareTo (b));

Hier de parameters een en b hebben geen expliciet gedefinieerde typen. Hun typen worden afgeleid als Geheel getal in de eerste Lambda Expression en als Draad in de seconde.

5. Conclusie

In dit korte artikel hebben we Type Inference besproken, dat samen met generieke geneesmiddelen en Lambda Expression ons in staat stelt om beknopte Java-code te schrijven.

Zoals gewoonlijk is de volledige broncode te vinden op Github.