MethodUtils.java でどのように機能するのか気になったので、中を調べてみました。どの方法を最適な組み合わせとして使用するかを決定するために、すべての方法にコストがかかります。コストを計算するには、次の方法があります (余分な dbg 出力があります)。
/**
* Gets the number of steps required needed to turn the source class into the
* destination class. This represents the number of steps in the object hierarchy
* graph.
* @param srcClass The source class
* @param destClass The destination class
* @return The cost of transforming an object
*/
private static float getObjectTransformationCost(Class srcClass, Class destClass) {
System.out.println("----------- start calculate cost from " + srcClass + " to " + destClass + "------------");
float cost = 0.0f;
while (destClass != null && !destClass.equals(srcClass)) {
System.out.println(srcClass + " and " + destClass + " are " + (destClass.equals(srcClass)? " equal" : " not equal"));
if (destClass.isInterface() && isAssignmentCompatible(destClass,srcClass)) {
// slight penalty for interface match.
// we still want an exact match to override an interface match, but
// an interface match should override anything where we have to get a
// superclass.
cost += 0.25f;
break;
}
cost++;
destClass = destClass.getSuperclass();
}
/*
* If the destination class is null, we've travelled all the way up to
* an Object match. We'll penalize this by adding 1.5 to the cost.
*/
if (destClass == null) {
cost += 1.5f;
}
System.out.println("COST IS " + cost);
return cost;
}
出力は
--- setters:
setData x
setData y
setData y
--- invokeMethod
----------- start calculate cost from class Lolka$DataZ to class Lolka$DataX------------
class Lolka$DataZ and class Lolka$DataX are not equal
class Lolka$DataZ and class java.lang.Object are not equal
COST IS 3.5
----------- start calculate cost from class Lolka$DataZ to class Lolka$DataY------------
class Lolka$DataZ and class Lolka$DataY are not equal
class Lolka$DataZ and class Lolka$DataX are not equal
class Lolka$DataZ and class java.lang.Object are not equal
COST IS 4.5
setData x
したがって、invokeMethode は、DataX の変換が 1 つの継承レベル フォーム オブジェクトであり、DataY が 2 であると想定します。したがって、DataX メソッドは「安価」です。それがその背後にあるロジックです。
UPD:
dest を src に変更しても問題なく動作するので、
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;
}
出力は
--- setters:
setData x
setData y
setData y
--- invokeMethod
setData y