[Java] pour les programmeurs confirmés...

pour les programmeurs confirmés... [Java] - Java - Programmation

Marsh Posté le 18-06-2002 à 15:16:47    

je cherche à utiliser un fichier XML pour lancer une méthode, plus précisément un constructeur. Je vous donne un exemple parlant (en tout cas j'espère !
Voici un morceu de mon fichier XML :

Code :
  1. <monObjet class="Truc">
  2. <param type="String" value="salut"/>
  3. <param type="int" value="10"/>
  4. <param type="boolean" value="true"/>
  5. </monObjet>


 
le but, c'est que je lance ceci :

Code :
  1. new Truc( "salut", 10, true )


évidemment, ça doit être générique, et c'est bien ça le pb !!!
 
Pour le moment, je récupère la classe, en utilisant Class.forName(  "Truc" )
puis je récupére les constructors associés par getConstructors et enfin un petit getParamatersType pour savoir quels sont les types des paramètres à passer à chaque contructeur...
Bref, le soucis, c'est d'arriver à faire un constructors[j].newInstance( monTableauDeParametres )


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 15:16:47   

Reply

Marsh Posté le 18-06-2002 à 15:23:16    

et c'est quoi ton problème ?
 
déjà, tu peux faire un Class.getDeclaredConstructor(Class[] parameterTypes) , ca ira plus vite.
 
ensuite, tu as juste à faire un appel Constructor.newInstance(Object[] initargs) avec les paramètres que tu auras mit dans le tableau

Reply

Marsh Posté le 18-06-2002 à 15:26:29    

benou a écrit a écrit :

déjà, tu peux faire un Class.getDeclaredConstructor(Class[] parameterTypes) , ca ira plus vite.


c vrai que ça c pas mal, mais il faut des Class, comme ça se passe si j'ai des types primitifs comme boolean ou int ?


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 15:44:11    

Il me semble; que plutôt de faire avec un getParamatersType, tu devrais directement construire ton tableau d'arguments, en utilisant les objets associés aux types primitifs : la Javadoc de java.lang.reflect.Constructor explique que :  
 
"If the corresponding formal parameter has a primitive type, an unwrapping conversion is attempted to convert the object value to a value of the primitive type. If this attempt fails, the creation throws an IllegalArgumentException.
 
If, after possible unwrapping, the parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion, the creation throws an IllegalArgumentException. "
 
Ouala...

Reply

Marsh Posté le 18-06-2002 à 15:46:30    

parfait, je teste tout ça ! (il assure bien le package java.lang.reflect)


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 15:49:00    

Ouais, mais il rame...C'est pour ça que je ne saurait trop te conseiller de gérer du cache : à chaque instanciation de constructeur, ou de classe, essaie de le garder qqpart en mémoire (genre, dans une hashtable indexée par nom complet de classe, qui contient des HashTable avec les cionstructeurs, par exemple) histoire que quand tu as une nouvelle instantiaton à faire, tu va d'abord regarder dans la hashtable si tu a pas déjà fait le boulot 30 secondes avant.

Reply

Marsh Posté le 18-06-2002 à 15:54:18    

z0rglub a écrit a écrit :

c vrai que ça c pas mal, mais il faut des Class, comme ça se passe si j'ai des types primitifs comme boolean ou int ?  




ca pose pas de problème les types primitif :
 

Code :
  1. public class Test {
  2.    public static void main (String[] args) throws Exception{     
  3.       Class intClasse = int.class;
  4.       Class stringClasse  = String.class;
  5.       java.lang.reflect.Method method = stringClasse.getDeclaredMethod("substring", new Class[] {intClasse});
  6.       Object[] params = {new Integer(3)};
  7.       System.out.println(method.invoke("coucou!!", params));     
  8.    }
  9. }

Reply

Marsh Posté le 18-06-2002 à 16:15:15    

mon pb, c'est d'avoir un int dans le Class[] je vois pas comment faire (sachant que je ne sais pas à l'avance que ce sera un int !)
par ce que  Class.forName( "int" ) çame renvoie une ClassNotFoundException :D ...


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 16:17:50    

topic pour développeurs confirmés tu disais ...
Integer c pour les blairos ?  :sarcastic:

Reply

Marsh Posté le 18-06-2002 à 16:19:08    

HappyHarry a écrit a écrit :

topic pour développeurs confirmés tu disais ...
Integer c pour les blairos ?  :sarcastic:  




yep, comme tu dis, mais tu peux m'expliquer plus précisément ?


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 16:19:08   

Reply

Marsh Posté le 18-06-2002 à 16:20:06    

Bah, tu te fais un p'tit parser :  
 
Soit le mec met un nom de classe complet (genre Boolean, ou Integer...) et si il met un nom de type primitif, tu instancies la bonne classe...C'est pas sorcier à faire, et y'a pâs des masses de types primitifs.

Reply

Marsh Posté le 18-06-2002 à 16:20:11    

hé ben ...

Reply

Marsh Posté le 18-06-2002 à 16:20:29    

z0rglub a écrit a écrit :

mon pb, c'est d'avoir un int dans le Class[] je vois pas comment faire (sachant que je ne sais pas à l'avance que ce sera un int !)
par ce que  Class.forName( "int" ) çame renvoie une ClassNotFoundException :D ...  




Je vois pas d'autre solutions que de faire plein de if ...
 
fait-toi une méthode getClassObject(String type) qui te retourne le Class à mettre dans le tableau d'argument :
 
if (type.equals("int" ))
   return int.class;
...
else  
   return Class.forName(type);

Reply

Marsh Posté le 18-06-2002 à 16:27:11    

HappyHarry a écrit a écrit :

hé ben ...  




bon tu vois, que c pas si simple...
 
je voulais un truc générique, mais je vais devoir faire tout un tas de if...
j'avais déjà un if, qui vérifiais la présence de "." parce que par défaut on peut mettre "String" au lieu de "java.lang.String" parce que Class.forName( "String" ) -> ClassNotFoundException


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 16:28:47    

z0rglub a écrit a écrit :

 
bon tu vois, que c pas si simple...
 
je voulais un truc générique, mais je vais devoir faire tout un tas de if...
j'avais déjà un if, qui vérifiais la présence de "." parce que par défaut on peut mettre "String" au lieu de "java.lang.String" parce que Class.forName( "String" ) -> ClassNotFoundException  




 
"he ben..." c t pour hé ben en voila un qui a pas lu toute la doc et qui connait pas les wrappers pour les types primitifs

Reply

Marsh Posté le 18-06-2002 à 16:32:18    

HappyHarry a écrit a écrit :

 
"he ben..." c t pour hé ben en voila un qui a pas lu toute la doc et qui connait pas les wrappers pour les types primitifs  




 
pourquoi tu cherches à l'ennerver ??? C'et vrai que le titre est racoleur et n'explique pas le thème du post, mais c'est pas une raison pour être sur son dos comme ca. Son roblème est pas aussi simple que tu essaye de lui faire croire.
 
Les Wrappers ne règlent pas tous les problèmes !
comment faire la différence entre une méthode void f(Integer i) et  void f(int i) ??
 
alors aide le plutot si tu as l'habitude de ce genre de problème !

Reply

Marsh Posté le 18-06-2002 à 16:33:18    

HappyHarry a écrit a écrit :

 
"he ben..." c t pour hé ben en voila un qui a pas lu toute la doc et qui connait pas les wrappers pour les types primitifs  




en plus je suis d'accord avec lui : je trouve que la série de if pour tester tous les types primitifs n'est pas propre. Si quelqu'un connaît une autre méthode, je suis preneur aussi !

Reply

Marsh Posté le 18-06-2002 à 16:38:55    

HappyHarry a écrit a écrit :

 
 
"he ben..." c t pour hé ben en voila un qui a pas lu toute la doc et qui connait pas les wrappers pour les types primitifs  




et puis je suis pas nul au point de pas savoir qu'il y a des Integer, Float... mais ce n'est absolument pas applicable dans ce cas précis...
Sinon, le titre n'est pas si racoleur, et je savais pas koi mettre parce que c'est un pb assez tiré par les cheveux...


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 16:43:48    

On dit "Cappillotracté", jeune homme! :D:D

Reply

Marsh Posté le 18-06-2002 à 16:50:29    

bon, sinon tu t'en sort avec la série de if ?

Reply

Marsh Posté le 18-06-2002 à 16:51:48    

moi je serais plutot d'accord avec gfive en fait : imposer une norme pour le nommage des types, ca te simplifiera la vie

Reply

Marsh Posté le 18-06-2002 à 16:55:10    

benou a écrit a écrit :

bon, sinon tu t'en sort avec la série de if ?  




Code :
  1. private java.lang.Class getClassFromString ( String stringType ) throws ClassNotFoundException
  2. {
  3.  if ( stringType.equals( "int" ) )
  4.  {
  5.   return int.class;
  6.  }
  7.  if ( stringType.equals( "byte" ) )
  8.  {
  9.   return byte.class;
  10.  }
  11.  if ( stringType.equals( "short" ) )
  12.  {
  13.   return short.class;
  14.  }
  15.  if ( stringType.equals( "long" ) )
  16.  {
  17.   return long.class;
  18.  }
  19.  if ( stringType.equals( "boolean" ) )
  20.  {
  21.   return boolean.class;
  22.  }
  23.  if ( stringType.equals( "float" ) )
  24.  {
  25.   return float.class;
  26.  }
  27.  if ( stringType.equals( "double" ) )
  28.  {
  29.   return double.class;
  30.  }
  31.  if ( stringType.equals( "char" ) )
  32.  {
  33.   return char.class;
  34.  }
  35.  if ( stringType.indexOf( "." ) == -1 )
  36.  {
  37.   return java.lang.Class.forName( "java.lang." + stringType );
  38.  }
  39.  else
  40.  {
  41.   return java.lang.Class.forName( stringType );
  42.  }
  43. }


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 16:58:57    

ouais ... c'est pas très beau mais je sais pas comment faire autrement.  
 
Pour optimiser, tu peux mettre les Class des types primitifs dans une HashMap. La recherche sera plus rapide ...

Reply

Marsh Posté le 18-06-2002 à 17:16:56    

ok, alors j'ai fait ça :

Code :
  1. primitveTypes = new HashMap ();
  2.   primitveTypes.put( "int", int.class );
  3.   primitveTypes.put( "byte", byte.class );
  4.   primitveTypes.put( "short", short.class );
  5.   primitveTypes.put( "long", long.class );
  6.   primitveTypes.put( "boolean", boolean.class );
  7.   primitveTypes.put( "float", float.class );
  8.   primitveTypes.put( "double", double.class );
  9.   primitveTypes.put( "int", char.class );


primitveTypes est un Map static
puis

Code :
  1. if ( stringType.toLowerCase().equals( stringType ) )
  2.  {
  3.   return ( Class )primitveTypes.get( stringType );
  4.  }


(je considère que si le type sous forme de chaîne est le même en minuscule et initial, c'est un type primitif... et non une classe


Message édité par z0rglub le 18-06-2002 à 17:17:32

---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 18:02:35    

cado :  
 

Code :
  1. public class Test {
  2.  
  3.    private static final java.util.Map primitveTypes = new java.util.HashMap ();
  4.    static {
  5.       primitveTypes.put( "int", int.class );
  6.       primitveTypes.put( "byte", byte.class );
  7.       primitveTypes.put( "short", short.class );
  8.       primitveTypes.put( "long", long.class );
  9.       primitveTypes.put( "boolean", boolean.class );
  10.       primitveTypes.put( "float", float.class );
  11.       primitveTypes.put( "double", double.class );
  12.       primitveTypes.put( "char", char.class );
  13.    }
  14.    public static Class getClass(String typeName) throws ClassNotFoundException {
  15.       Class classe = (Class) primitveTypes.get(typeName);
  16.       if (classe != null) {
  17.          return classe;
  18.       }
  19.       else {
  20.          try {
  21.             return Class.forName( typeName );
  22.          } catch (ClassNotFoundException e) {
  23.             try {
  24.                 return Class.forName("java.lang." + typeName );
  25.             } catch (ClassNotFoundException ex) {
  26.                throw e;
  27.             }
  28.          }
  29.       }
  30.    }
  31.    public static void main (String[] args) throws Exception {     
  32.       System.out.println(getClass("java.lang.String" ));
  33.       System.out.println(getClass("String" ));
  34.       System.out.println(getClass("int" ));
  35.       System.out.println(getClass("TralalaPouetPouet" ));
  36.    }
  37. }


Message édité par benou le 18-06-2002 à 18:03:43
Reply

Marsh Posté le 18-06-2002 à 18:09:49    

ok, super sympa, c'est plus propre que ma méthode en tout cas !


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 18:16:10    

ah oui, et puis je lutte encore pour un truc : comme je fais pour que lorsque le type trouvé est int, il me transforme ma chaîne value ="1" en 1 tout court, idem pour un boolean que je met à true, vous voyez ce que je veux dire...


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 19:55:10    

z0rglub a écrit a écrit :

ah oui, et puis je lutte encore pour un truc : comme je fais pour que lorsque le type trouvé est int, il me transforme ma chaîne value ="1" en 1 tout court, idem pour un boolean que je met à true, vous voyez ce que je veux dire...  




 
Pour le "1" en 1 c Interger.parseInt(String)
et pour le booléen Boolean.getBoolean(String)

Reply

Marsh Posté le 18-06-2002 à 20:11:55    

ok, en fait je vais faire une méthode pour récupérer à partir de type et value (sous forme de string tous les 2) un objet de type Class + 1 Objet de type Object en essayant de rendre compte de tous les cas


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 23:05:31    

anntention : regarde bien l'exemple que je t'avais fillé prédement avec l'appel à la méthode substring : le tableau de Class indique bien la class String, pourtant c'est un Integer qu'il faut mettre dans le tableau de paramètre.
 
donc il ne faut pas que tu utilises Integer.parseInt(String).
 
Tu peux utiliser le constructeur de Integer pour ca : new Integer(String)

Reply

Marsh Posté le 18-06-2002 à 23:10:31    

comme le but, c'est de récupérer un int, il va falloir faire new Integer(String).intValue()
idem pour le Boolean


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 23:14:35    

non. Le but c'est de passer une valeur en paramètre au constructeur (enfin si j'ai bien compris). Comme tu dois mettre cette valeur dans un tableau d'objet, tu ne peut pas mettre un int (int n'est pas un objet). Tu mets un Integer dedans, en la méthode se débrouillera pour se rendre compte qu'il lui faut en faite un int et ferra la transformation toute seule.
 
Regarde l'expemple que je t'avais donné ...

Reply

Marsh Posté le 18-06-2002 à 23:17:34    

benou a écrit a écrit :

Regarde l'expemple que je t'avais donné ...



désolé mais j'ai pas compris toute ta syntaxe alors j'ai abandonné. Pour ce qui est du constructeur qui "comprend" qu'il doit transformer le Integer en int, c super, ça me simplifie le travail en fait !


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le 18-06-2002 à 23:23:01    

z0rglub a écrit a écrit :

 
 Pour ce qui est du constructeur qui "comprend" qu'il doit transformer le Integer en int, c super, ça me simplifie le travail en fait !  




uniquement au moment du invoke. mon exemple marche avec une méthode mais pour un constructeur c'est pareil.
 
je vais simplifier la syntaxe et commenter pour que tu comprennes ...

Reply

Marsh Posté le 18-06-2002 à 23:40:54    

et voila :

Code :
  1. import java.lang.reflect.*;
  2. import java.util.*;
  3. public class Test {
  4.    public static void main (String[] args) throws Exception {           
  5.       // on récupère l'objet class du type  
  6.       Class arrayListClass  = ArrayList.class;
  7.       // on aurait aussi pu ecrire ca :
  8.       // Class  arrayListClass = Class.forName("java.util.ArrayList" )
  9.      
  10.       // on va maintenant récpérer le constructeur qui prend en paramètre un int  
  11.       // pour ca, il faut construire un tableau représentant le type des paramètre
  12.       Class[] paramTypes = new Class[1]; // il n'y a qu'un seul paramètre  
  13.       // le paramètre est de type int => on récupère l'object Class du type int
  14.       Class intClass = int.class;     
  15.       paramTypes[0] = intClass;
  16.       // on récupère l'objet constructeur  
  17.       Constructor consturcteur = arrayListClass.getDeclaredConstructor(paramTypes);
  18.       // il faut maintenant invoker le constructeur.
  19.       // pour ca, il faut construire un tableau d'objet contenant les valeurs des paramètre
  20.       Object[] paramsValues = new Object[1];
  21.       // ASTUCE : on ne peut pas mettre de int dans un tableau d'objet : int est un type primitif
  22.       // on va utiliser le wrapper correspondant au int à savoir le Integer
  23.       // la métpode newInstance du constructeur se débrouillera pour récupérer le int
  24.       paramsValues[0] = new Integer(3);
  25.       // maintenant on utilise le constructeur pur créer une nouvelle instance d'ArrayList
  26.       ArrayList arrayListDynamique = (ArrayList) consturcteur.newInstance(paramsValues);
  27.       // on peut maintenant se servir de l'arrayList normalement :
  28.       arrayListDynamique.add("c'est cool" );
  29.       arrayListDynamique.add("ca marche !" );
  30.       System.out.println(arrayListDynamique);
  31.    }
  32.  
  33. }

Reply

Marsh Posté le 19-06-2002 à 10:06:52    

parfait je viens de tester, et avec un new Integer( "3" ); (c'est ça qui est important aussi) et ça marche parfaitement. merci encore...


---------------
Ma galerie photo créée avec Piwigo et hébergée sur Piwigo.com
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed