Here you can find the source of getMethod(Class> klass, String methodName, Class>... paramTypes)
public static Method getMethod(Class<?> klass, String methodName, Class<?>... paramTypes)
//package com.java2s; //License from project: LGPL import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Main { public static Method getMethod(Class<?> klass, String methodName, Class<?>... paramTypes) { List<Method> candidates = new ArrayList<Method>(); // NOTE: getMethods() includes inherited methods outer: for (Method method : klass.getMethods()) { if (method.getName().equals(methodName)) { Class<?>[] methodParamTypes = method.getParameterTypes(); if (paramTypes.length == methodParamTypes.length || (method.isVarArgs() && paramTypes.length >= methodParamTypes.length - 1)) { // method has correct name and # of parameters if (method.isVarArgs()) { for (int i = 0; i < methodParamTypes.length - 1; i++) { if (paramTypes[i] != null && !methodParamTypes[i].isAssignableFrom(paramTypes[i])) { continue outer; }/*from w ww . j a v a 2 s . co m*/ } if (methodParamTypes.length == paramTypes.length + 1) { // no param is specified for the optional vararg // spot } else if (methodParamTypes.length == paramTypes.length && methodParamTypes[paramTypes.length - 1] .isAssignableFrom(paramTypes[paramTypes.length - 1])) { // an array is specified for the last param } else { Class<?> varClass = methodParamTypes[methodParamTypes.length - 1].getComponentType(); for (int i = methodParamTypes.length - 1; i < paramTypes.length; i++) { if (paramTypes[i] != null && !varClass.isAssignableFrom(paramTypes[i])) { continue outer; } } } } else { for (int i = 0; i < methodParamTypes.length; i++) { if (paramTypes[i] != null && !methodParamTypes[i].isAssignableFrom(paramTypes[i])) { continue outer; } } } candidates.add(method); } } } if (candidates.size() == 0) { return null; } else if (candidates.size() == 1) { return candidates.get(0); } else { // There are several possible methods. Choose the most specific. // Throw away any var-args options. // Non var-args methods always beat var-args methods and we're going // to say that if we have two var-args // methods, we cannot choose between the two. Iterator<Method> itr = candidates.iterator(); while (itr.hasNext()) { Method m = itr.next(); if (m.isVarArgs()) { // the exception is if an array is actually specified as the // last parameter if (m.getParameterTypes().length != paramTypes.length || !m.getParameterTypes()[paramTypes.length - 1] .isAssignableFrom(paramTypes[paramTypes.length - 1])) itr.remove(); } } // If there are no candidates left, that means we had only var-args // methods, which we can't choose // between. if (candidates.size() == 0) return null; Method a = candidates.get(0); boolean ambiguous = false; for (int j = 1; j < candidates.size(); j++) { Method b = candidates.get(j); Class<?>[] aTypes = a.getParameterTypes(); Class<?>[] bTypes = b.getParameterTypes(); int aScore = 0, bScore = 0; // increment score if distance is greater for a given parameter for (int i = 0; i < aTypes.length; i++) { if (aTypes[i] != null) { int distA = getDist(aTypes[i], paramTypes[i]); int distB = getDist(bTypes[i], paramTypes[i]); if (distA > distB) { bScore++; } else if (distA < distB) { aScore++; } else if (distA == 1000) { // both are interfaces // if one interface extends the other, that // interface is lower in the hierarchy (more // specific) and wins if (!aTypes[i].equals(bTypes[i])) { if (aTypes[i].isAssignableFrom(bTypes[i])) bScore++; else if (bTypes[i].isAssignableFrom(aTypes[i])) aScore++; } } } } // lower score wins if (aScore == bScore) { ambiguous = true; } else if (bScore > aScore) { a = b; // b wins ambiguous = false; } } if (ambiguous) return null; return a; } } private static int getDist(Class<?> superClass, Class<?> klass) { if (klass.isArray()) { if (superClass.isArray()) { superClass = superClass.getComponentType(); klass = klass.getComponentType(); } else { // superClass must be Object. An array fitting into an Object // must be more general than an array fitting into an Object[] // array. return 3000; } } if (superClass.equals(klass)) return 0; if (superClass.equals(Object.class)) return 2000; // specifying Object is always the most general if (superClass.isInterface()) { return 1000; } int dist = 0; while (true) { dist++; klass = klass.getSuperclass(); if (superClass.equals(klass)) return dist; } } }