Inferenza generalizzata del tipo di destinazione in Java

1. Introduzione

L'inferenza del tipo è stata introdotta in Java 5 per integrare l'introduzione dei generici ed è stata sostanzialmente ampliata nelle seguenti versioni di Java, che viene anche chiamata inferenza generalizzata del tipo di destinazione.

In questo tutorial, esploreremo questo concetto con esempi di codice.

2. Generici

I generics ci hanno fornito molti vantaggi come una maggiore sicurezza dei tipi, evitare errori di casting del tipo e algoritmi generici. Puoi leggere di più sui generici in questo articolo.

Tuttavia, l'introduzione dei generici ha comportato la necessità di scrivere codice boilerplate a causa della necessità di passare parametri di tipo . Alcuni esempi sono:

Map
    
      mapOfMaps = new HashMap
     
      (); List strList = Collections.emptyList(); List intList = Collections.emptyList();
     
    

3. Digitare Inference Before Java 8

Per ridurre la prolissità del codice non necessaria, è stata introdotta in Java l'inferenza del tipo, il processo di deduzione automatica di tipi di dati non specificati di un'espressione in base alle informazioni contestuali.

Ora possiamo richiamare gli stessi tipi e metodi generici senza specificare i tipi di parametro. Il compilatore deduce automaticamente i tipi di parametro quando necessario.

Possiamo vedere lo stesso codice usando il nuovo concetto:

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

Nell'esempio precedente, in base ai tipi restituiti previsti List e List , il compilatore è in grado di dedurre il parametro di tipo al seguente metodo generico:

public static final  List emptyList() 

Come possiamo vedere, il codice risultante è conciso. Ora, possiamo chiamare metodi generici come un metodo ordinario se il parametro di tipo può essere dedotto.

In Java 5, potremmo eseguire l'inferenza del tipo in contesti specifici come mostrato sopra.

Java 7 ha ampliato i contesti in cui poteva essere eseguito. Ha introdotto l'operatore del diamante. Puoi leggere di più sull'operatore diamante in questo articolo.

Ora possiamo eseguire questa operazione per i costruttori di classi generiche in un contesto di assegnazione. Uno di questi esempi è:

Map
    
      mapOfMapsInferred = new HashMap();
    

Qui, il compilatore Java utilizza il tipo di assegnazione previsto per dedurre i parametri del tipo al costruttore HashMap .

4. Inferenza del tipo di destinazione generalizzata - Java 8

Java 8 ha ulteriormente ampliato l'ambito di Type Inference. Ci riferiamo a questa capacità di inferenza espansa come inferenza generalizzata del tipo di destinazione. Puoi leggere i dettagli tecnici qui.

Java 8 ha introdotto anche le espressioni Lambda. Le espressioni Lambda non hanno un tipo esplicito. Il loro tipo viene dedotto osservando il tipo di destinazione del contesto o della situazione. Il tipo di destinazione di un'espressione è il tipo di dati che il compilatore Java si aspetta a seconda di dove appare l'espressione.

Java 8 supporta l'inferenza utilizzando Target-Type in un contesto di metodo. Quando invochiamo un metodo generico senza argomenti di tipo espliciti, il compilatore può esaminare la chiamata del metodo e le dichiarazioni del metodo corrispondenti per determinare l'argomento di tipo (o gli argomenti) che rendono applicabile la chiamata.

Esaminiamo un codice di esempio:

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

Nel codice, ArrayList non fornisce esplicitamente l'argomento del tipo. Quindi, il compilatore deve dedurlo. Innanzitutto, il compilatore esamina gli argomenti del metodo add. Quindi, esamina i parametri passati a diverse chiamate.

Esegue l' analisi dell'inferenza di applicabilità delle chiamate per determinare se il metodo si applica a queste chiamate . Se più metodi sono applicabili a causa del sovraccarico, il compilatore sceglierà il metodo più specifico.

Then, the compiler performs invocation type inference analysis to determine the type arguments.The expected target types are also used in this analysis. It deduces the arguments in the three instances as ArrayList, ArrayList and ArrayList.

Target-Type inference allows us to not specify types for lambda expression parameters:

List intList = Arrays.asList(5, 2, 4, 2, 1); Collections.sort(intList, (a, b) -> a.compareTo(b)); List strList = Arrays.asList("Red", "Blue", "Green"); Collections.sort(strList, (a, b) -> a.compareTo(b));

Here, the parameters a and b do not have explicitly defined types. Their types are inferred as Integer in the first Lambda Expression and as String in the second.

5. Conclusion

In questo breve articolo, abbiamo esaminato l'inferenza del tipo, che insieme a generics e Lambda Expression ci consente di scrivere codice Java conciso.

Come al solito, il codice sorgente completo può essere trovato su Github.