private static int moreSpecific()

in src/main/java/org/apache/commons/jexl3/internal/introspection/MethodKey.java [569:618]


    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;
    }