invoke()
ne marche pas sur
les types primitifs ?
invoke()
lève l'exception
MultipleMatchingMethodsException
?
Il existe deux méthodes statiques dans la classe
MultiMethod
:
MultiMethod create(Class clazz,String name,int argLength) MultiMethod create(Class clazz,String name,int argLength,boolean onlyPublic)
clazz
name
argLength
onlyPublic
false
par défaut)
La visibilité d'une multi-méthode correspond à la visibilité de
la méthode la plus visible.
Avec PUBLIC > PROTECTED > PACKAGE > PRIVATE
donc avec les méthodes :
public void print(double d) {...} private void print(int i) {...}
La multi-méthode correspondante aura une visibilité PUBLIC.
class Test { static class A { public void m() { System.out.println("A"); } } static class B extends A { public void m() { System.out.println("B"); } } public static void main(String[] args) throws Exception { Method m=B.class.getMethod("m",null); m.invoke(new A(),null); // throws IllegalArgumentException, object isn't an instance // of the declaring class MultiMethod mm=MultiMethod.create(B.class,"m",0,true); mm.invoke(new A(),null); // print "A" } }
Contrairement au mécanisme des Methodes
,
l'implementation des multi-méthodes considère que les méthodes
A.m() et B.m() sont en faite, une seul et meme méthode donc
il est possible d'appeler la multi-méthode "m" de la classe B
avec un objet de la class A.
Oui, c'est le un cas ou le mécanisme des multi-méthodes passe
outre le mécanisme de visibilité de Java.
Le mécanisme des multi-méthodes regarde uniquement la visibilité
de la multi-méthode et non, la visibilité de chaque méthode
sous-jacente.
class Algo { private void print(int i) { System.out.println("int "+i); } public void print(double d) { System.out.println("double "+d); } } class Test { public static void main(String[] args) throws Exception { MultiMethod mm=MultiMethod.create(Algo.class,"print",1); mm.invoke(new Algo(),new Object[]{new Integer(3)}, new Class[]{Integer.TYPE}); } }
invoke()
ne marche pas sur
les types primitifs ?
Il n'y a pas de convertion explicite pour transformer
un Integer en int lors de la recherche de la meilleur méthode
(uniquement lors de la recherche, il n'y pas de problème lors
de l'appel)
Si l'on veut utiliser la convertion, il faut le faire explicitement
en indiquant à la méthode
invoke(Object, Object[], Class[])
quel est le type
réel de l'objet, par exemple en utilisant
Integer.TYPE
Cette méthode permet aussi d'appeler la meilleur méthode non-plus
en fonction du type réel des paramètres mais en fonction du
type des classes passées en paramètre.
Ceci pourrait être rajouter dans les futures version du framework.
class Test { void print(int i) { System.out.println("int "+i); } public static void main(String[] args) throws Exception { MultiMethod mm=MultiMethod.create(Test.class,"print",1); // mm.invoke(new Test(),new Object[]{new Integer(3)}); // this method look for the method print(Integer) mm.invoke(new Test(),new Object[]{new Integer(3)}, new Class[]{Integer.TYPE}); } }
invoke()
lève l'exception
MultipleMatchingMethodsException
?
Cette exception est levé lorsque le mécanisme d'appel des
multi-méthodes détecte que plusieurs méthodes peuvent
être appelé suivant les arguments passés à la méthode
invoke
et que le mécanisme ne sait pas choisir la
meilleur méthode.
La résolution des conflits suis les mêmes règles que la résolution
statique des méthodes effectuée par le compilateur. (cf JLS).
class Test { class A implements Serializable, Cloneable { // ... } private static void m(Serializable s) { System.out.println("serializable"); } private static void m(Cloneable c) { System.out.println("cloneable"); } public static void main(String[] args) throws Exception { MultiMethod mm=MultiMethod.create(Test.class,"m",1); mm.invoke(null,new Object[]{new A()}); // throws MultipleMatchingMethodsException } }