Question

Je dois effectuer des appels de méthode de réflexion en Java. Ces appels incluront des méthodes dont les arguments sont des types primitifs (int, double, etc.). La méthode permettant de spécifier de tels types lors de la recherche de la méthode de manière réflexive est int.class, double.class, etc.

Le problème, c’est que j’accepte les entrées d’une source externe qui spécifieront les types de manière dynamique. Par conséquent, je dois également proposer ces références de classe de manière dynamique. Imaginez un fichier délimité d'une liste de noms de méthodes 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 &) pour cette classe. exemple de retour. Est-il possible d'utiliser cette méthode ou une autre pour récupérer le type primitif Classes?

Modifier: Merci à tous les répondants. Il semble clair qu’il n’existe aucun moyen intégré de faire ce que je veux, alors je vais me contenter de réutiliser la classe ClassUtils du framework Spring. Il semble contenir un remplaçant pour Class.forName () qui fonctionnera avec mes exigences.

Était-ce utile?

La solution

Le cadre Spring contient une classe d’utilitaires ClassUtils qui contient la méthode statique forName. Cette méthode peut être utilisée dans le but exact que vous avez décrit.

Au cas où vous n'aimeriez pas avoir de dépendance sur Spring: le le code source de la méthode peut être trouvé , par exemple ici sur leur référentiel public. Le code source de la classe est sous licence sous le modèle Apache 2.0.

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

Modifier: Merci aux commentateurs de Vid Horv & # 225; th et à Patrick pour avoir signalé le lien brisé.

Autres conseils

Les instances de Class pour les types primitifs peuvent être obtenues comme vous l'avez dit, par exemple. int.class , mais il est également possible d'obtenir les mêmes valeurs en utilisant quelque chose comme Integer.TYPE . Chaque classe de wrapper de primitive contient un champ statique, TYPE , qui contient l'instance de classe de primitive correspondante.

Vous ne pouvez pas obtenir la classe primitive via forName , mais vous pouvez l'obtenir à partir d'une classe 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

Il vous suffit probablement de mapper les primitives et, pour le reste des classes, effectuez l'option "forName". 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.
Map<String,Class> builtInMap = new HashMap<String,Class>();{
       builtInMap.put("int", Integer.TYPE );
       builtInMap.put("long", Long.TYPE );
       builtInMap.put("double", Double.TYPE );
       builtInMap.put("float", Float.TYPE );
       builtInMap.put("bool", Boolean.TYPE );
       builtInMap.put("char", Character.TYPE );
       builtInMap.put("byte", Byte.TYPE );
       builtInMap.put("void", Void.TYPE );
       builtInMap.put("short", Short.TYPE );
}

En d’autres termes, créez une carte dans laquelle les types de primitives sont stockés. Si la description appartient à une primitive, utilisez la classe mappée. Cette carte peut également être chargée à partir d'un fichier de configuration externe, pour plus de souplesse, afin que vous ajoutiez String au lieu de java.lang.String ou que vous utilisiez une méthode similaire.

& do; quelque chose Chaîne oui | non "

Il y a beaucoup de ce genre de code dans les projets OS comme les librairies Struts, Hibernate, Spring et Apache (pour n'en citer que quelques-unes), vous n'avez donc pas besoin de commencer à zéro.

BTW. Je n'ai pas compilé le code ci-dessus, mais je suis presque sûr qu'il fonctionne avec de petites modifications, ne me votez pas pour ça.

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

Malheureusement, un certain nombre de méthodes de classe ne traitent pas les primitives de manière cohérente. Une façon courante de contourner cela dans forName est d’avoir une table 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;
}

Le code suivant explique comment obtenir la classe d'un type primitif dont le nom de champ est connu, par exemple. dans ce cas, 'sampleInt'.

public class CheckPrimitve {
    public static void main(String[] args) {
        Sample s = new Sample();
        try {
            System.out.println(s.getClass().getField("sampleInt").getType() == int.class); // returns true
            System.out.println(s.getClass().getField("sampleInt").getType().isPrimitive()); // returns true
        } catch (NoSuchFieldException e) {          
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }       
    }
}

class Sample {
    public int sampleInt;
    public Sample() {
        sampleInt = 10;
    }
}

On peut également vérifier si une valeur donnée est primitive ou non en obtenant sa classe wrapper respective ou sa valeur de champ.

    public class CheckPrimitve {
        public static void main(String[] args) {
            int i = 3;
            Object o = i;
            System.out.println(o.getClass().getSimpleName().equals("Integer")); // returns true
            Field[] fields = o.getClass().getFields();
            for(Field field:fields) {
                System.out.println(field.getType()); // returns {int, int, class java.lang.Class, int}
            }
        }
    }

Google Guava propose com.google.common.primitives.Primitives pour ce type de produit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top