in src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java [485:534]
private static int moreSpecific(final Class<?>[] a, final Class<?>[] c1, final Class<?>[] c2) {
// compare lengths to handle comparisons where the size of the arrays
// doesn't match, but the methods are both applicable due to the fact
// that one is a varargs method
if (c1.length > a.length) {
return LESS_SPECIFIC;
}
if (c2.length > a.length) {
return MORE_SPECIFIC;
}
if (c1.length > c2.length) {
return MORE_SPECIFIC;
}
if (c2.length > c1.length) {
return LESS_SPECIFIC;
}
// same length, keep ultimate param offset for vararg checks
final int length = c1.length;
final int ultimate = c1.length - 1;
// ok, move on and compare those of equal lengths
for (int i = 0; i < length; ++i) {
if (c1[i] != c2[i]) {
final boolean last = i == ultimate;
// argument is null, prefer an Object param
if (a[i] == Void.class) {
if (c1[i] == Object.class && c2[i] != Object.class) {
return MORE_SPECIFIC;
}
if (c1[i] != Object.class && c2[i] == Object.class) {
return LESS_SPECIFIC;
}
}
// prefer primitive on non-null arg, non-primitive otherwise
boolean c1s = isPrimitive(c1[i], last);
boolean c2s = isPrimitive(c2[i], last);
if (c1s != c2s) {
return c1s == (a[i] != Void.class) ? MORE_SPECIFIC : LESS_SPECIFIC;
}
// if c2 can be converted to c1 but not the opposite,
// c1 is more specific than c2
c1s = isStrictConvertible(c2[i], c1[i], last);
c2s = isStrictConvertible(c1[i], c2[i], last);
if (c1s != c2s) {
return c1s ? MORE_SPECIFIC : LESS_SPECIFIC;
}
}
}
// Incomparable due to non-related arguments (i.e.foo(Runnable) vs. foo(Serializable))
return INCOMPARABLE;
}