54 votes

Trouver dynamiquement la classe qui représente une primitive de type Java

J'ai besoin de faire quelques réfléchissant les appels de méthode en Java. Ces appels vous inclure des méthodes qui ont des arguments qui sont des types primitifs (int, double, etc.). La façon de spécifier les types lors de la recherche de la méthode reflectively est int.class, double.class, etc.

Le problème est que je suis accepter l'entrée d'une source extérieure qui doit spécifier les types de manière dynamique. Donc, j'ai besoin de trouver ces références de Classe dynamique. Imaginez un fichier délimité par une liste de noms de méthode avec des listes de types de paramètres:

doSomething int double
doSomethingElse java.lang.String boolean

Si l'entrée était quelque chose comme java.lang.String, je sais que je pourrais utiliser Class.forName("java.lang.String") à la Classe en instance de retour. Est-il possible d'utiliser cette méthode, ou d'une autre, pour obtenir le type primitif des Classes de retour?

Edit: Merci à tous les répondants. Il semble clair qu'il n'est pas intégrée de façon à proprement faire ce que je veux, donc je me contenterai de réutilisation de l' ClassUtils classe du framework Spring. Il semble contenir un remplacement pour la Classe.forName() qui va travailler avec mes exigences.

32voto

Daniel Spiewak Points 30706

L' Class des cas pour les types primitifs sont obtenus comme vous l'avez dit par exemple à l'aide int.class, mais il est également possible d'obtenir les mêmes valeurs en utilisant quelque chose comme Integer.TYPE. Chaque primitif classe contient un champ statique, TYPE, qui a le même primitif instance de classe.

Vous ne pouvez pas obtenir la primitive de la classe via forName, mais vous pouvez l'obtenir à partir d'une classe qui est facilement disponible. Si vous devez absolument utiliser la réflexion, vous pouvez essayer quelque chose comme ceci:

Class clazz = Class.forName("java.lang.Integer");
Class intClass = clazz.getField("TYPE").get(null);

intClass.equals(int.class);         // => true

22voto

Synoli Points 163

Le framework Spring contient une classe utilitaire ClassUtils qui contient la méthode statique forName. Cette méthode peut être utilisée pour la fonction exacte que vous avez décrit.

Dans le cas où vous ne voulez pas avoir une dépendance sur le Printemps: la source de la méthode peut être trouvé à l'e. g. ici. Le code source de la classe est sous licence Apache 2.0 modèle.

Notez cependant que l'algorithme utilise une codé en dur carte des types primitifs.

20voto

OscarRyz Points 82553

Probablement vous avez juste besoin de la carte les primitives et pour le reste de la classe effectuer le "forName" la méthode:

Je voudrais faire quelque chose comme:

void someWhere(){
     String methodDescription = "doSomething int double java.lang.Integer java.lang.String"
     String [] parts = methodDescription.split();
     String methodName= parts[0]
     Class [] paramsTypes = getParamTypes( parts ); // Well, not all the array, but a, sub array from 1 to arr.length..  

    Method m = someObject.class.getMethod( methodName, paramTypes );
    etc. etc etc.
}

public Class[] paramTypes( String [] array ){
     List<Class> list = new ArrayList<Class>();
     for( String type : array ) {
         if( builtInMap.contains( type )) {
             list.add( builtInMap.get( type ) );
          }else{
             list.add( Class.forName( type ) );
          }
     }
     return list.toArray();
}  

// That's right.
private Map<String,Class> builtInMap = new HashMap<String,Class>();{
       builtInMap("int", Integer.TYPE );
       builtInMap("long", Long.TYPE );
       builtInMap("double", Double.TYPE );
       builtInMap("float", Float.TYPE );
       builtInMap("bool", Boolean.TYPE );
       builtInMap("char", Character.TYPE );
       builtInMap("byte", Byte.TYPE );
       builtInMap("void", Void.TYPE );
       builtInMap("short", Short.TYPE );
}

C'est, de créer une carte où les primitives types sont stockées et si la description appartenir à une primitive puis utilisez le mappé classe. Cette carte peut également être chargé à partir d'un fichier de configuration externe, pour ajouter de la flexibilité de sorte que vous ajouter une Chaîne comme un construit, au lieu de java.lang.Chaîne ou potentiellement méthode comme ceci.

"doSomething chaîne oui|non"

Il y a beaucoup de ce genre de code dans les OS des projets comme Struts, Hibernate, Spring et Apache libs ( pour n'en citer que quelques-uns ) , de sorte que vous n'avez pas besoin de démarrer à partir de zéro.

BTW. Je n'ai pas compiler le code ci-dessus, mais je suis assez sûr qu'elle fonctionne avec peu de modifications de ne pas voter de moi pour cela.

5voto

thSoft Points 5513

Apache Commons Lang a ClassUtils.getClass(String), qui prend en charge les types primitifs.

3voto

Peter Lawrey Points 229686

Un certain nombre de méthodes de la Classe ne gère pas les primitives de façon cohérente malheureusement. Une façon courante autour de cette forName est d'avoir un tableau comme;

private static final Map<String, Class> BUILT_IN_MAP = 
    new ConcurrentHashMap<String, Class>();

static {
    for (Class c : new Class[]{void.class, boolean.class, byte.class, char.class,  
            short.class, int.class, float.class, double.class, long.class})
        BUILT_IN_MAP.put(c.getName(), c);
}

public static Class forName(String name) throws ClassNotFoundException {
    Class c = BUILT_IN_MAP.get(name);
    if (c == null)
        // assumes you have only one class loader!
        BUILT_IN_MAP.put(name, c = Class.forName(name));
    return c;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X