web-dev-qa-db-fra.com

Java Génériques - Obtenir un cours?

J'ai une liste, programmée comme ceci: public class MyList<T>. Existe-t-il un moyen d'utiliser la variable T pour obtenir le nom de la classe (afin que je puisse, à l'intérieur de MyList, savoir si T est String, Socket, etc.)?

EDIT: Peu importe, trouvé la réponse ici .

75
ryyst

Réponse courte: Vous ne pouvez pas.

Réponse longue:

En raison de la manière dont les génériques sont implémentés en Java, le type générique T n'est pas conservé au moment de l'exécution. Néanmoins, vous pouvez utiliser un membre de données privé:

public class Foo<T> 
{
    private Class<T> type;

    public Foo(Class<T> type) { this.type = type; } 
}

Exemple d'utilisation:

Foo<Integer> test = new Foo<Integer>(Integer.class);
111
duffymo

J'aime la solution de

http://www.nautsch.net/2008/10/28/class-von-type-parameter-Java-generics/

public class Dada<T> {

    private Class<T> typeOfT;

    @SuppressWarnings("unchecked")
    public Dada() {
        this.typeOfT = (Class<T>)
                ((ParameterizedType)getClass()
                .getGenericSuperclass())
                .getActualTypeArguments()[0];
    }
...
55
wutzebaer

Vous voyez le résultat de Type Erasure . De cette page ...

Lorsqu'un type générique est instancié, le compilateur traduit ces types par une technique appelée type erasure - un processus dans lequel le compilateur supprime toutes les informations relatives aux paramètres de type et aux arguments de type d'une classe ou d'une méthode. La suppression de type active les applications Java qui utilisent des génériques pour maintenir la compatibilité binaire avec les bibliothèques et les applications Java créées avant les génériques.

Par exemple, Box <String> est traduit en type Box, appelé type brut - un type brut est une classe générique ou un nom d'interface sans argument de type. Cela signifie que vous ne pouvez pas savoir quel type d'objet est utilisé par une classe générique au moment de l'exécution.

Cela ressemble aussi à ceci question qui a un très bonne réponse aussi .

25
Andrew White

Je ne suis pas sûr à 100% si cela fonctionne dans tous les cas (nécessite au moins Java 1.5):

import Java.lang.reflect.Field;
import Java.lang.reflect.ParameterizedType;
import Java.lang.reflect.Type;
import Java.util.HashMap;
import Java.util.Map;

public class Main 
{
    public class A
    {   
    }

    public class B extends A
    {       
    }


    public Map<A, B> map = new HashMap<Main.A, Main.B>();

    public static void main(String[] args) 
    {

        try
        {
            Field field = Main.class.getField("map");           
            System.out.println("Field " + field.getName() + " is of type " + field.getType().getSimpleName());

            Type genericType = field.getGenericType();

            if(genericType instanceof ParameterizedType)
            {
                ParameterizedType type = (ParameterizedType) genericType;               
                Type[] typeArguments = type.getActualTypeArguments();

                for(Type typeArgument : typeArguments) 
                {   
                    Class<?> classType = ((Class<?>)typeArgument);                  
                    System.out.println("Field " + field.getName() + " has a parameterized type of " + classType.getSimpleName());
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }    
}

Cela produira:

La carte de terrain est de type Carte
La carte de terrain a un type paramétré de A
La carte de terrain a un type paramétré de B

4
esaj

Je peux obtenir la classe du type générique de cette façon:

class MyList<T> {
  Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(MyList.class, this.getClass()).get(0);
}

Vous avez besoin de deux fonctions à partir de ce fichier: http://code.google.com/p/hibernate-generic-dao/source/browse/trunk/dao/src/main/Java/com/googlecode/genericdao/ dao/DAOUtil.Java

Pour plus d'explications: http://www.artima.com/weblogs/viewpost.jsp?thread=20886

2
Peter Tseng