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
Post a Comment