⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 methodmap.java

📁 freemaker安装软件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            throw new Error();
        }
        
        private static int moreSpecific(Class[] c1, Class[] c2)
        {
            boolean c1MoreSpecific = false;
            boolean c2MoreSpecific = false;
            for(int i = 0; i < c1.length; ++i)
            {
                if(c1[i] != c2[i])
                {
                    c1MoreSpecific = 
                        c1MoreSpecific ||
                        isMoreSpecific(c1[i], c2[i]);
                    c2MoreSpecific = 
                        c2MoreSpecific ||
                        isMoreSpecific(c2[i], c1[i]);
                }
            }
            if(c1MoreSpecific)
            {
                if(c2MoreSpecific)
                {
                    return INDETERMINATE;
                }
                return MORE_SPECIFIC;
            }
            if(c2MoreSpecific)
            {
                return LESS_SPECIFIC;
            }
            return INDETERMINATE;
        }
        
        
        /**
         * Returns all methods that are applicable to actual
         * parameter classes represented by this ClassString object.
         */
        LinkedList getApplicables(List methods)
        {
            LinkedList list = new LinkedList();
            for (Iterator imethod = methods.iterator(); imethod.hasNext();)
            {
                Object method = imethod.next();
                if(isApplicable(method))
                {
                    list.add(method);
                }
                
            }
            return list;
        }
        
        /**
         * Returns true if the supplied method is applicable to actual
         * parameter classes represented by this ClassString object.
         * 
         */
        private boolean isApplicable(Object method)
        {
            Class[] methodArgs = getParameterTypes(method);
            if(methodArgs.length != classes.length)
            {
                return false;
            }
            for(int i = 0; i < classes.length; ++i)
            {
                if(!isMethodInvocationConvertible(methodArgs[i], classes[i]))
                {
                    return false;
                }
            }
            return true;
        }
        
        /**
         * Determines whether a type represented by a class object is
         * convertible to another type represented by a class object using a 
         * method invocation conversion, treating object types of primitive 
         * types as if they were primitive types (that is, a Boolean actual 
         * parameter type matches boolean primitive formal type). This behavior
         * is because this method is used to determine applicable methods for 
         * an actual parameter list, and primitive types are represented by 
         * their object duals in reflective method calls.
         * @param formal the formal parameter type to which the actual 
         * parameter type should be convertible
         * @param actual the actual parameter type.
         * @return true if either formal type is assignable from actual type, 
         * or formal is a primitive type and actual is its corresponding object
         * type or an object type of a primitive type that can be converted to
         * the formal type.
         */
        private static boolean isMethodInvocationConvertible(Class formal, Class actual)
        {
            // Check for identity or widening reference conversion
            if(formal.isAssignableFrom(actual))
            {
                return true;
            }
            // Check for boxing with widening primitive conversion. Note that 
            // actual parameters are never primitives.
            if(formal.isPrimitive())
            {
                if(formal == Boolean.TYPE && actual == Boolean.class)
                    return true;
                if(formal == Character.TYPE && actual == Character.class)
                    return true;
                if(formal == Byte.TYPE && actual == Byte.class)
                    return true;
                if(formal == Short.TYPE &&
                   (actual == Short.class || actual == Byte.class))
                    return true;
                if(formal == Integer.TYPE && 
                   (actual == Integer.class || actual == Short.class || 
                    actual == Byte.class))
                    return true;
                if(formal == Long.TYPE && 
                   (actual == Long.class || actual == Integer.class || 
                    actual == Short.class || actual == Byte.class))
                    return true;
                if(formal == Float.TYPE && 
                   (actual == Float.class || actual == Long.class || 
                    actual == Integer.class || actual == Short.class || 
                    actual == Byte.class))
                    return true;
                if(formal == Double.TYPE && 
                   (actual == Double.class || actual == Float.class || 
                    actual == Long.class || actual == Integer.class || 
                    actual == Short.class || actual == Byte.class))
                    return true; 
            }
            // Special case for BigDecimals as we deem BigDecimal to be
            // convertible to any numeric type - either object or primitive.
            // This can actually cause us trouble as this is a narrowing 
            // conversion, not widening. 
            return isBigDecimalConvertible(formal, actual);
        }
        
        private String listArgumentTypes()
        {
            StringBuffer buf = 
                new StringBuffer(classes.length * 32).append('(');
            for(int i = 0; i < classes.length; ++i)
            {
                buf.append(classes[i].getName()).append(',');
            }
            buf.setLength(buf.length() - 1);
            return buf.append(')').toString();
        }
    }

    /**
     * Determines whether a type represented by a class object is 
     * convertible to another type represented by a class object using a 
     * method invocation conversion, without matching object and primitive
     * types. This method is used to determine the more specific type when
     * comparing signatures of methods.
     * @return true if either formal type is assignable from actual type, 
     * or formal and actual are both primitive types and actual can be
     * subject to widening conversion to formal.
     */
    private static boolean isMoreSpecific(Class specific, Class generic)
    {
        // Check for identity or widening reference conversion
        if(generic.isAssignableFrom(specific))
        {
            return true;
        }
        // Check for widening primitive conversion.
        if(generic.isPrimitive())
        {
            if(generic == Short.TYPE && (specific == Byte.TYPE))
                return true;
            if(generic == Integer.TYPE && 
               (specific == Short.TYPE || specific == Byte.TYPE))
                return true;
            if(generic == Long.TYPE && 
               (specific == Integer.TYPE || specific == Short.TYPE || 
                specific == Byte.TYPE))
                return true;
            if(generic == Float.TYPE && 
               (specific == Long.TYPE || specific == Integer.TYPE || 
                specific == Short.TYPE || specific == Byte.TYPE))
                return true;
            if(generic == Double.TYPE && 
               (specific == Float.TYPE || specific == Long.TYPE || 
                specific == Integer.TYPE || specific == Short.TYPE || 
                specific == Byte.TYPE))
                return true; 
        }
        return isBigDecimalConvertible(generic, specific);
    }
    
    private static boolean isBigDecimalConvertible(Class formal, Class actual)
    {
        // BigDecimal 
        if(BIGDECIMAL_CLASS.isAssignableFrom(actual))
        {
            if(NUMBER_CLASS.isAssignableFrom(formal))
            {
                return true;
            }
            if(formal.isPrimitive() && 
               formal != Boolean.TYPE && formal != Character.TYPE)
            {
               return true;
            }
        }
        return false;
    }
    
    /**
     * A comparator that sorts Class objects by a composite key
     * (!clazz.isInterface(), clazz.getName()). Used to select between multiple
     * most specific common types. 
     */
    private static final Comparator CLASS_ORDER = new Comparator() {
        public int compare(Object o1, Object o2) {
            Class c1 = (Class)o1;
            Class c2 = (Class)o2;
            if(c1.isInterface()) {
                if(!c2.isInterface()) {
                    return 1;
                }
            }
            else if(c2.isInterface()) {
                return -1;
            }
            return c1.getName().compareTo(c2.getName());
        }
    };
    
    private static Class getMostSpecificCommonType(Class c1, Class c2)
    {
        if(c1 == c2) {
            return c1;
        }
        if(c2.isPrimitive()) {
            if(c2 == Byte.TYPE) c2 = Byte.class;
            else if(c2 == Short.TYPE) c2 = Short.class;
            else if(c2 == Character.TYPE) c2 = Character.class;
            else if(c2 == Integer.TYPE) c2 = Integer.class;
            else if(c2 == Float.TYPE) c2 = Float.class;
            else if(c2 == Long.TYPE) c2 = Long.class;
            else if(c2 == Double.TYPE) c2 = Double.class;
        }
        Set a1 = getAssignables(c1, c2);
        Set a2 = getAssignables(c2, c1);
        a1.retainAll(a2);
        if(a1.isEmpty()) {
            // Can happen when at least one of the arguments is an interface, as
            // they don't have Object at the root of their hierarchy
            return Object.class;
        }
        // Gather maximally specific elements. Yes, there can be more than one 
        // thank to interfaces. I.e., if you call this method for String.class 
        // and Number.class, you'll have Comparable, Serializable, and Object as 
        // maximal elements. 
        List max = new ArrayList();
outer:  for (Iterator iter = a1.iterator(); iter.hasNext();) {
            Class clazz = (Class) iter.next();
            for (Iterator maxiter = max.iterator(); maxiter.hasNext();) {
                Class maxClazz = (Class) maxiter.next();
                if(isMoreSpecific(maxClazz, clazz)) {
                    // It can't be maximal, if there's already a more specific
                    // maximal than it.
                    continue outer;
                }
                if(isMoreSpecific(clazz, maxClazz)) {
                    // If it's more specific than a currently maximal element,
                    // that currently maximal is no longer a maximal.
                    maxiter.remove();
                }
            }
            // If we get here, no current maximal is more specific than the
            // current class, so it is considered maximal as well
            max.add(clazz);
        }
        if(max.size() > 1) {
            // If there is more than one maximal element, choose one. We favor 
            // classes over interfaces. However, if all maximal elements are
            // interfaces (which can happen if both original arguments to this
            // method were interfaces), we choose the one that comes first 
            // alphabetically -- this is admittedly arbitrary, but is at least 
            // deterministic. It doesn't matter much as  this is used for is 
            // creating class hints, and all this is also a rather rare corner
            // case.
            Collections.sort(max, CLASS_ORDER);
        }
        return (Class)max.get(0);
    }

    private static Set getAssignables(Class c1, Class c2)
    {
        Set s = new HashSet();
        collectAssignables(c1, c2, s);
        return s;
    }
    
    private static void collectAssignables(Class c1, Class c2, Set s)
    {
        if(c1.isAssignableFrom(c2)) {
            s.add(c1);
        }
        Class sc = c1.getSuperclass();
        if(sc != null) {
            collectAssignables(sc, c2, s);
        }
        Class[] itf = c1.getInterfaces();
        for(int i = 0; i < itf.length; ++i) {
            collectAssignables(itf[i], c2, s);
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -