2
votes

Java - Obtenir le nom de la classe générique

J'ai les deux classes suivantes:

String className = new TypeToken<T>() {}.getClass().getName().toString();

Dans le Generic , j'ai une méthode dont j'ai besoin pour obtenir le nom de la classe qui est passée T

Est-ce possible en Java? Je sais qu'en C #, j'utiliserais simplement typeof.

J'ai essayé de faire ce qui suit:

class Generic<T> 
{

}

class Foo extends Generic<Student>
{

}

Ceci cependant ne pas fournir le nom et ne fournit que Generic$1


3 commentaires

Cochez ceci stackoverflow.com/questions/6624113/...


Vous ne pouvez pas utilement créer un jeton de type générique. Vous pouvez obtenir la classe à partir d'un jeton de type non générique (par exemple, new TypeToken () {} ou new TypeToken > () {} ) en regardant les paramètres de type de son supertype générique; mais ce paramètre de type est la variable de type T pour ce jeton de type.


J'ai rouvert car ce n'est pas une copie de la question revendiquée. Dans ce cas, le type est accessible via Foo (bien qu'il y ait une exigence que la sous-classe n'utilise pas de paramètre ici).


4 Réponses :


0
votes

Je suppose que Generic est toujours sous-classé avec une classe qui fournit le paramètre de type avec une classe réelle, comme dans le code Foo . Dans ce cas, les informations de type sont toujours disponibles en utilisant Class.getGenericSupertype . Voici un exemple rapide.

import java.lang.reflect.*;

class Generic<T> 
{
    public String name() {
        Class<?> clazz = this.getClass();
        for (;;) {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass == null) {
                throw new IllegalStateException();
            }
            if (superClass == Generic.class) {
                Type genericSuper = clazz.getGenericSuperclass();
                if (genericSuper instanceof ParameterizedType) {
                    ParameterizedType parameterized = (ParameterizedType)genericSuper;
                    Type[] params = parameterized.getActualTypeArguments();
                    if (params.length == 1) {
                        Type param = params[0];
                        if (param instanceof Class<?>) {
                            return ((Class<?>)param).getName();
                        }
                    }
                }
                throw new IllegalStateException();
            }
            clazz = superClass;
        }
    }
}

class Foo extends Generic<Student>
{

}
interface Student {}

interface Code {
   static void main(String[] args) {
       System.err.println(new Foo().name());
   }
}

Cela ne concerne que des cas simples. Par exemple, si Foo étend Generic > alors T n'est pas une Class.


0 commentaires

2
votes

Utilisez la méthode getGenericSuperclass () et vérifiez s'il s'agit d'un ParameterizedType puis récupérez tous les arguments avec getActualTypeArguments () qui renvoie un tableau Type , rappelez-vous qu'une classe générique peut utiliser plus d'un type comme Map (Map )
public Class<?> getGenericType(Object obj) {
    Class<?> genericType = null;
    Type gnrcType = obj.getClass().getGenericSuperclass();
    if (gnrcType instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) gnrcType;
        Type types[] = parameterizedType.getActualTypeArguments();

        if (types != null && types.length > 0) {
            Type type = types[0];
            if (type instanceof Class) {
                genericType = (Class<?>) type;
            }
        }
    }
    return genericType;
}


0 commentaires

-1
votes

C # et Java implémentent les génériques de manière très différente.

C # a de vrais génériques et des informations génériques au moment de l'exécution. Pour des raisons de compatibilité descendante, Java utilise l'effacement de type - c'est toute la magie générique qui se trouve dans le compilateur et il remplace Object par T partout et à l'exécution, vous n'avez aucune connaissance du type générique.

Les génériques Java sont toujours meilleurs que les modèles C ++, ce qui n'est pas mieux que la substitution de macros à la compilation. Mais Java ne peut pas faire de génériques de style C # sans rompre la rétrocompatibilité avec l'ancienne version de runtime / bytecode.

En résumé, vous ne pouvez pas faire cela en Java.


0 commentaires

0
votes

Le moyen facile d'obtenir le nom d'une classe générique.

Définir une classe générique

public void exampleMethod(GenericClass type) {
    String fullName= type.getType().getCanonicalName(); //"com.example.MyEntity"
    String sortName= type.getType().getSimpleName(); //"MyEntity"
}

}

Utilisez cette classe générique comme un paramètre

GenericClass type = new GenericClass(MyEntity.class);
exampleMethod(type);

Dans la méthode exampleMethod

public class GenericClass<T> {

private final Class<T> type;

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

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


0 commentaires