private static Method getMostSpecific(List methods, Class[] classes)
        throws AmbiguousException
    {
        LinkedList<Method> applicables = getApplicables(methods, classes);

        if(applicables.isEmpty())
        {
            return null;
        }

        if(applicables.size() == 1)
        {
            return applicables.getFirst();
        }

        /*
         * This list will contain the maximally specific methods. Hopefully at
         * the end of the below loop, the list will contain exactly one method,
         * (the most specific method) otherwise we have ambiguity.
         */

        LinkedList<Method> maximals = new LinkedList<Method>();

        for ( Method app : applicables )
        {
            Class[] appArgs = app.getParameterTypes();
            boolean lessSpecific = false;

            for ( Iterator maximal = maximals.iterator(); !lessSpecific && maximal.hasNext(); )
            {
                Method max = (Method) maximal.next();

                switch ( moreSpecific( appArgs, max.getParameterTypes() ) )
                {
                    case MORE_SPECIFIC:
                    {
                        /*
                         * This method is more specific than the previously
                         * known maximally specific, so remove the old maximum.
                         */

                        maximal.remove();
                        break;
                    }

                    case LESS_SPECIFIC:
                    {
                        /*
                         * This method is less specific than some of the
                         * currently known maximally specific methods, so we
                         * won't add it into the set of maximally specific
                         * methods
                         */

                        lessSpecific = true;
                        break;
                    }
                }
            }

            if ( !lessSpecific )
            {
                maximals.addLast( app );
            }
        }

        if(maximals.size() > 1)
        {
            // We have more than one maximally specific method
            throw new AmbiguousException();
        }

        return maximals.getFirst();
    }