Frage

Da Generika eingeführt wurden, Klasse parametrisiert, so dass List.class Klasse erzeugt. Das ist klar.

Was ich nicht in der Lage bin, um herauszufinden, ist, wie man eine Instanz der Klasse des Typs zu erhalten, die sich parametrisiert wird, das heißt der Klasse >. Wie in diesem Snippet:

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);
    }
}

Ich laufe in Variationen dieses Problem sehr oft und ich weiß noch nicht, ob ich etwas nur vermissen, oder wenn es wirklich keinen besseren Weg. Vielen Dank für die Anregungen.

War es hilfreich?

Lösung

Die Klasse-Klasse ist eine Laufzeit-Darstellung eines Typs. Da parametrisierte Typen Typ Löschung zur Laufzeit durchlaufen, würde das Klassenobjekt für die Klasse der gleiche sein wie für die Klasse > und Klasse >.

Der Grund, warum Sie sie nicht instanziiert können die .class-Notation ist, dass dies eine spezielle Syntax für die Klasse Literale verwendet wird. Die Java Language Specification speziell verbietet dies Syntax, wenn der Typ parametrisiert, weshalb List .class- ist nicht erlaubt.

Andere Tipps

Klassen repräsentieren Klassen durch einen Klassenlader geladen, die rohe Typen sind. Um einen parametrisierte Typen darzustellen, verwendet java.lang.reflect.ParameterizedType.

Ich glaube nicht, dass Sie das tun können, was Sie wollen. Zum einen nicht Ihren instantiate Methode wissen, dass seine mit einer parametrierbaren Art zu tun (man könnte genauso gut passieren es java.util.Date.class). Zweitens, weil die Löschung, etwas besonders spezifisch mit parametrisierte Typen zur Laufzeit zu tun ist schwierig oder unmöglich.

Wenn Sie das Problem auf eine andere Weise zu nähern waren, gibt es andere kleine Tricks, die Sie tun können, wie Typinferenz:

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();
    }
}

Das einzige, was Sie tun können, ist instantiate List<String> direkt und seine getClass() nennen:

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

Bei den Typen mit mehreren abstrakten Methoden wie List, ist dies ziemlich umständlich. Aber leider, Unterklasse Bauer fordert (wie new ArrayList<String>) oder Fabrikmethoden (Collections.<String>emptyList()) funktioniert nicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top