Domanda

Da quando sono stati introdotti i generici, Class è parametrizzata, in modo che List.class produca Class<List>.Questo è chiaro.

Quello che non riesco a capire è come ottenere un'istanza di Class di tipo parametrizzata essa stessa, vale a direClasse<Lista<Stringa>>.Come in questo frammento:

public class GenTest {
    static <T> T instantiate(Class<T> clazz) throws Exception {
        return clazz.newInstance();
    }
    public static void main(String[] args) throws Exception {
        // Is there a way to avoid waring on the line below
        // without using  @SuppressWarnings("unchecked")?
        // ArrayList.class is Class<ArrayList>, but I would like to
        // pass in Class<ArrayList<String>>
        ArrayList<String> l = GenTest.instantiate(ArrayList.class);
    }
}

Mi imbatto in varianti di questo problema abbastanza spesso e ancora non so se mi sfugge qualcosa o se davvero non esiste un modo migliore.Grazie per i suggerimenti

È stato utile?

Soluzione

La classe Class è una rappresentazione runtime di un tipo.Poiché i tipi parametrizzati vengono sottoposti a cancellazione del tipo in fase di esecuzione, l'oggetto classe per Class sarebbe lo stesso di Class<List<Integer>> e Class<List<String>>.

Il motivo per cui non è possibile istanziarli utilizzando la notazione .class è che si tratta di una sintassi speciale utilizzata per i valori letterali delle classi.IL Specifica del linguaggio Java vieta specificamente questa sintassi quando il tipo è parametrizzato, motivo per cui List<String>.class non è consentito.

Altri suggerimenti

Le classi rappresentano le classi caricate da un caricatore di classi, che sono tipi grezzi.Per rappresentare un tipo con parametri, utilizzare java.lang.reflect.ParameterizedType.

Non penso che tu possa fare quello che stai provando.In primo luogo, il tuo metodo di istanziazione non sa che ha a che fare con un tipo parametrizzato (potresti passarlo altrettanto facilmente java.util.Date.class).In secondo luogo, a causa della cancellazione, eseguire operazioni particolarmente specifiche con i tipi parametrizzati in fase di esecuzione è difficile o impossibile.

Se dovessi affrontare il problema in un modo diverso, ci sono altri piccoli trucchi che puoi usare, come l'inferenza del tipo:

public class GenTest
{
    private static <E> List<E> createList()
    {
        return new ArrayList<E>();
    }

    public static void main(String[] args)
    {
        List<String> list = createList();
        List<Integer> list2 = createList();
    }
}

L'unica cosa che puoi fare è istanziare List<String> direttamente e chiamalo getClass():

instantiate(new List<String>() { ... }.getClass());

Per i tipi con più metodi astratti come List, questo è abbastanza imbarazzante.Ma sfortunatamente, chiamando i costruttori di sottoclassi (come new ArrayList<String>) o metodi di fabbrica (Collections.<String>emptyList()) non funzionano.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top