Frage zu Collection-Generics in Subklassen

smigfu

Neues Mitglied
Moin,

Ich hab ein Problem mit Generic in Subklassen. Ich habe ein Klasse die mit "T" getypt ist. Im Prinzip will ich damit den Typ einer Klasse wissen.

Java:
public static class Upper<T>
{
        private Class<T> type;
	public Upper(final Class<T> clazz) {...}

        public Class<T> getType()
        {
                return type;
        }
}

Das funktioniert auch soweit korrekt. Allerdings sobald ich mit getypten Collections anfange, wird es kompliziert, z.B.:

Java:
public static class Lower extends Upper<List<String>>
{
	public Lower()
	{
		super(List.class);
	}
}

Das compiliert natürlich nicht, ebenso wenig wie:

Java:
public static class Lower extends Upper<List<String>>
{
	public Lower()
	{
		super(List<String>.class);
	}
}

Die einzige Möglichkeit ist:

Java:
public static class Lower extends Upper<List>
{
	public Lower()
	{
		super(List.class);
	}
}

Allerdings liefert getType() nun natürlich Class<List> und nicht Class<List<T>>. Hat jemand vielleicht eine Idee, wie das zu bewerkstelligen ist? Und falls nicht eine Erklärung warum das nicht geht? So ganz klar ist mir das im Moment nämlich nicht.

Danke.

Gruß
Philipp

PS: Ja ich weiß, dass die Info zur Laufzeit eh nicht vorhanden ist, mir geht es hier auch nur um die Compilezeit 🙂
 
Also was geht, ist den Constructor von [c]Upper[/c] als [c]public Upper(final Class<? super T> clazz)[/c] zu definieren. Ob damit deine [c]...[/c] noch gehen, weiß ich natürlich nicht.
 
Marco hat's schon geschrieben, man bekommt nur den Interfacetypen (List) geliefert. Der generische Parameter ist zur Laufzeit weg. Denn Generics gibt es nur zur Compilezeit. Zur Laufzeit ist das alles weg. Hintergrund ist, dass auch nicht generischer (Alt-)Code noch ausührbar sein soll. Das einzige, was geht, ist Deine Klasse um einen weiteren generischen Parameter E (Elementtype) zu erweitern, wenn Du unbeding den Typ der Elemente generisch brauchst.
 
Moin,

Ich habe ein Klasse die mit "T" getypt ist. Im Prinzip will ich damit den Typ einer Klasse wissen.

Falls man die Klassen so umbauen kann, dass der Typ Parameter zum Upper Bound der gefragten Klasse wird, ist die Typ Information auch noch zur Laufzeit vorhanden.

Java:
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

abstract class Upper<T> {


    public abstract void set(final T t);


    public Set<Type> getType() {

        final Set<Type> result = new HashSet<>();

        for (final Method method : getClass().getMethods())
            if (method.getName().equals("set"))
                for (final Type generic : method.getGenericParameterTypes())
                    if (generic instanceof TypeVariable) {

                        final TypeVariable<?> tv = (TypeVariable<?>) generic;

                        for (final Type type : tv.getBounds())
                            result.add(type);

                    }

        return result;

    }

}


public class Lower<T extends List<Integer>> extends Upper<T> {

    @Override
    public void set(final T t) {

        //

    }


    public static void main(final String[] args) {

        final Lower<?> l = new Lower<>();
        System.out.println(l.getType()); // [java.util.List<java.lang.Integer>]

    }


}

Viele Grüße
Fancy
 
Danke für die Antworten. Leider zielen viele davon auf die Runtime ab.

Was mich interessiert ist, warum der Compiler damit Probleme hat (siehe auch mein PS 🙂).
 
Wie man das formulieren sollte, weiß ich nicht. Das Problem ist, dass der Compiler zwar das List<String> sieht, aber es eben kein Objekt vom Typ "Klasse von List<String>" gibt, sondern nur vom Typ "Klasse von List". Wie gesagt, mit einem TypeToken würde es wohl gehen (die verwenden intern richtig, richtig RICHTIG üble Magic um die Typen zu capturen...)
 

Neue Themen


Zurück
Oben