Find best matching writeMethod with Java reflection -


commons beanutils getmatchingaccessiblemethod finds match, not best possible match.

consider simple example:

public class testreflection extends testcase {    public static class beana {     private datax data;     public beana setdata(datax x) {       system.out.println("setdata x");       return this;     }     public beana setdata(datay y) {       system.out.println("setdata y");       return this;     }   }    static class datax {   }   static class datay extends datax {   }   static class dataz extends datay {   }    public void testpropertyutils() {     try {       beana = new beana();       system.out.println("--- setters:");       a.setdata(new datax());       a.setdata(new datay());       a.setdata(new dataz());       system.out.println("--- invokemethod");       methodutils.invokemethod(a, "setdata", new dataz());     } catch (exception e) {       e.printstacktrace();     }   } } 

(hint: invokemethod uses getmatchingaccessiblemethod)

the above code outputs

--- setters: setdata x setdata y setdata y --- invokemethod setdata x 

the last line shoud "setdata y" because best match calling "setdata" dataz object should 1 datay in interface (just setdata(new dataz()) does).

is there way find best possible match or have code myself?

i curious how works in methodutils.java, looked inside. determine method should used best match, every method gain cost. calculate cost there method (with dbg-output):

/**  * gets number of steps required needed turn source class   * destination class. represents number of steps in object hierarchy   * graph.  * @param srcclass source class  * @param destclass destination class  * @return cost of transforming object  */ private static float getobjecttransformationcost(class srcclass, class destclass) {     system.out.println("----------- start calculate cost " + srcclass + " " + destclass + "------------");      float cost = 0.0f;     while (destclass != null && !destclass.equals(srcclass)) {         system.out.println(srcclass + " , " + destclass + " " + (destclass.equals(srcclass)? " equal" : " not equal"));         if (destclass.isinterface() && isassignmentcompatible(destclass,srcclass)) {             // slight penalty interface match.              // still want exact match override interface match,               // interface match should override have              // superclass.             cost += 0.25f;             break;         }         cost++;          destclass = destclass.getsuperclass();     }      /*      * if destination class null, we've travelled way       * object match. we'll penalize adding 1.5 cost.      */     if (destclass == null) {         cost += 1.5f;     }     system.out.println("cost " + cost);       return cost; } 

so output is

--- setters: setdata x setdata y setdata y --- invokemethod ----------- start calculate cost class lolka$dataz class lolka$datax------------ class lolka$dataz , class lolka$datax  not equal class lolka$dataz , class java.lang.object  not equal cost 3.5 ----------- start calculate cost class lolka$dataz class lolka$datay------------ class lolka$dataz , class lolka$datay  not equal class lolka$dataz , class lolka$datax  not equal class lolka$dataz , class java.lang.object  not equal cost 4.5 setdata x 

so invokemethode assumes converting datax 1 inheritance-level form object, , datay 2. datax-method "cheaper". thats logic behind that.

upd: changing dest src works fine, if use

private static float getobjecttransformationcost(class srcclass, class destclass) {     float cost = 0.0f;     while (srcclass != null && !destclass.equals(srcclass)) {         if (destclass.isinterface() && isassignmentcompatible(destclass,srcclass)) {             cost += 0.25f;             break;         }         cost++;          srcclass = srcclass.getsuperclass();     }      if (srcclass == null) {         cost += 1.5f;     }      return cost; } 

the output is

--- setters: setdata x setdata y setdata y --- invokemethod setdata y 

Comments

Popular posts from this blog

c# - SVN Error : "svnadmin: E205000: Too many arguments" -

c++ - Using OpenSSL in a multi-threaded application -

All overlapping substrings matching a java regex -