2009-09-06 8 views
2

Si j'ai des noms de fonctions stockés en tant que chaînes dans une table de hachage.
Existe-t-il un moyen d'accéder aux fonctions via les chaînes stockées? Je crains que la plateforme sur laquelle je travaille sur CLDC1.1/MIDP2.0 ne supporte pas Reflection.
Une solution de contournement possible? Étant donné un nom de fonction, vous pouvez utiliser la réflexion pour accéder à la méthode.Activation d'une fonction via une chaîne stockée dans Hashtable

Répondre

4

Il suffit d'utiliser une grande liste d'autre-ifs:

[...] 
} else if ("foo".equals(function)) { 
    target. foo(); 
} else if ("bar".equals(function)) { 
    target. bar(); 
[...] 

(Bien que je généralement aime pas essayer les alignements verticaux dans la source, je pense que dans des cas comme cela, il vaut bien la peine.)

Le stockage d'un foncteur dans la carte est une alternative, car la taille de l'objet peut être trop importante pour de nombreuses applications MIDP.

+0

La pensée de cela me rend reconnaissant de ne pas développer JavaME , du moins pas sur une plate-forme aussi limitée. – Yishai

+0

@Tom: Point concernant la mémoire a beaucoup de sens! En ce qui concerne la vitesse, ce qui serait plus rapide de rechercher la méthode HashTable ou le if/else-if. –

+1

Vous penseriez que 'Hashtable' serait rapide pour tous, mais le plus petit * n *. Cependant, je pense que la chaîne else-if devrait fonctionner rapidement. (Il est légèrement dépendant de l'implémentation. 'String.equals' pourrait utiliser le hachage pour rejeter presque toutes les chaînes non égales.) –

2

Outre le nom de la fonction, vous devez connaître sa classe, et avoir (ou créer par réflexion si elle a un constructeur noarg ou vous savez quels paramètres passer au constructeur) une instance (si la méthode n'est pas statique) et vous avoir à connaître les paramètres nécessaires pour passer à lui.

Une autre option consiste à utiliser la classe Method en tant que pointeur vers la fonction. Il a l'avantage de connaître sa classe et de connaître ses exigences en termes de paramètres. Il a l'inconvénient de ne pas être sérialisable.

EDIT: Il n'y a aucun moyen d'accéder à une méthode en Java sans réflexion en ayant juste son nom en tant que chaîne. Si vous voulez un pointeur alternatif à une méthode, vous pouvez utiliser une classe interne anonyme qui appelle la méthode que vous voulez implémenter une interface connue et la transmettre à votre carte. Ce ne serait pas approprié en tant que clé de la carte, mais cela fonctionnerait comme une valeur sur la carte.

+0

Existe-t-il une autre façon? .. une sans utiliser de réflexion? –

2

Je n'ai pas essayé de réflexion sur javame, mais sur javase vous pouvez utiliser la réflexion pour appeler dynamiquement une méthode.

L'extrait suivant est tiré de: http://java.sun.com/developer/technicalArticles/ALT/Reflection/

import java.lang.reflect.*; 

method2 public class { add public int (int a, int b) { retour a + b; }

public static void main(String args[]) 
    { 
    try { 
     Class cls = Class.forName("method2"); 
     Class partypes[] = new Class[2]; 
     partypes[0] = Integer.TYPE; 
     partypes[1] = Integer.TYPE; 
     Method meth = cls.getMethod(
      "add", partypes); 
     method2 methobj = new method2(); 
     Object arglist[] = new Object[2]; 
     arglist[0] = new Integer(37); 
     arglist[1] = new Integer(47); 
     Object retobj 
      = meth.invoke(methobj, arglist); 
     Integer retval = (Integer)retobj; 
     System.out.println(retval.intValue()); 
    } 
    catch (Throwable e) { 
     System.err.println(e); 
    } 
    } 

}

EDIT: Plutôt que d'utiliser if..then..else vous pouvez passer en fait revenir un certain nombre, et d'utiliser un commutateur, car il sera plus facile à lire, OMI.

Mais, peu importe, c'est probablement votre seule option compte tenu des limitations de JavaME.

+1

Avec Java5 et VarArgs et autoboxing, ce code peut être nettoyé beaucoup. – Yishai

+0

@ James, cela pourrait-il être fait sans réflexion? –

+0

@Kevin Boyd, je ne connais pas un moyen de le faire sans réflexion, car je ne peux même pas penser à un moyen de le faire avec AOP. Si vous avez besoin de cette capacité, vous pouvez regarder Groovy. Je vais y penser pendant que je suis au gymnase. @Yishai, le code peut être nettoyé, je pensais juste que montrer un exemple d'utilisation de la réflexion peut être utile, et je ne crois pas que JavaME supporte les génériques –

4

Class.forName() et newInstance() devraient être présents sur MIDP 1.1 et pourraient être utiles. Puisque vous n'avez pas de réflexion complète, vous pouvez créer une classe qui enveloppe tous les appels de fonction et les invoque. Cela suppose que vous connaissiez tous les appels de fonction à l'avance.

Vous aurez besoin de références à tous les objets sauf si vous faites des appels statiques. Un peu désordonné, mais ferait le travail.

public Object invoke(String name, Object[] args) { 
    Object f = functionMap.get(name); 
    if("f1".equals(name)) { 
     return ((SomeInterface1)f).someFunction1((SomeArg0) args[0]), ...); 
    } else if ("f2".equals(name)) { 
     return ((SomeInterface2)f).someFunction2((SomeArg0) args[0]), ...); 
    }...{ 
    } else if ("fN".equals(name)) { 
     return ((SomeInterfaceN)f).someFunctionN((SomeArg0) args[0]), ...); 
    } 
} 
1

Je traitent des questions similaires à Hecl, un interprète qui fonctionne sur J2ME. Cela dépend du nombre de chaînes que vous voulez traiter, mais une méthode qui fonctionne est d'utiliser le hachage pour rechercher un entier, puis l'utiliser dans une instruction switch, au lieu de la grande liste d'instructions if/then. En passant, vous pouvez utiliser le code source Hecl. C'est disponible sous licence libérale Apache.

+0

Je regardais Hecl hier! Quelle est la force de ses capacités d'interface utilisateur? –

+1

Il peut faire tout ce que J2ME peut faire. Quelqu'un a également contribué un port MWT. Vous ne voulez probablement pas l'utiliser pour un travail de canevas qui doit être * rapide *, comme il est interprété, mais pour les applications de base, ça va très bien! –

Questions connexes