当前访客身份:游客 [ 登录 | 加入 OSCHINA ]

代码分享

当前位置:
代码分享 » Java  » 常用工具方法
canghailan

Java反射

canghailan 发布于 2012年05月05日 1时, 3评/1666阅
分享到: 
收藏 +0
1

代码片段(14) [全屏查看所有代码]

1. [文件] Methods.java ~ 3KB     下载(24)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import canghailan.util.CachedLookup;
import canghailan.util.Lookup;
import canghailan.util.SimpleLRUCache;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author canghailan 2012-04-10 21:03
 */
public class Methods {
    private static final ExecutorService executorService = Executors.newCachedThreadPool();
    private static final Lookup<MethodIdentifier, Method> methodLookup = buildMethodLookup();

    private static Lookup<MethodIdentifier, Method> buildMethodLookup() {
        return new MethodLookup(buildOverloadingLookup());
    }

    private static Lookup<ClassNamePair, MethodSignature[]> buildOverloadingLookup() {
        return new CachedLookup<>(
                new OverloadingLookup(),
                new SimpleLRUCache<ClassNamePair, Future<MethodSignature[]>>(1000),
                executorService
        );
    }

    private static final Class<?>[] EMPTY_ARGUMENT_TYPES = new Class<?>[0];

    public static Class<?>[] getArgumentTypes(Object... args) {
        if (args.length == 0) {
            return EMPTY_ARGUMENT_TYPES;
        }
        Class<?>[] argTypes = new Class<?>[args.length];
        for (int i = 0; i < args.length; ++i) {
            argTypes[i] = args[i] == null ? null : args[i].getClass();
        }
        return argTypes;
    }

    public static Method getMethod(Class<?> cls, String name, Class<?>... argTypes) {
        return methodLookup.find(new MethodIdentifier(cls, name, argTypes));
    }

    public static Object invoke(Object object, String name, Object... args)
            throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        return invoke(object.getClass(), name, getArgumentTypes(args), object, args);
    }

    public static Object invokeStatic(Class<?> cls, String name, Object... args)
            throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        return invoke(cls, name, getArgumentTypes(args), null, args);
    }

    private static Object invoke(Class<?> cls, String name, Class<?>[] argTypes, Object object, Object... args)
            throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Method method = getMethod(cls, name, argTypes);
        if (method != null) {
            return method.invoke(object, args);
        }
        throw new NoSuchMethodException(invokeToString(cls, name, args));
    }

    private static String invokeToString(Class<?> cls, String name, Object... args) {
        StringBuilder buffer = new StringBuilder();
        buffer.append(cls.getName());
        buffer.append('.');
        buffer.append(name);
        buffer.append('(');
        if (args.length > 0) {
            for (Object arg : args) {
                buffer.append(arg).append(',');
            }
            buffer.setLength(buffer.length() - 1);
        }
        buffer.append(')');
        return buffer.toString();
    }
}

2. [文件] Fields.java ~ 3KB     下载(16)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import canghailan.util.CachedLookup;
import canghailan.util.Lookup;
import canghailan.util.SimpleLRUCache;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author canghailan 2012-04-10 21:03
 */
public class Fields {
    private static final ExecutorService executorService = Executors.newCachedThreadPool();
    private static final Lookup<ClassNamePair, Field> fieldLookup = buildFieldLookup();
    private static final Lookup<ClassNamePair, Method> propertyGetterLookup = buildPropertyGetterLookup();

    private static Lookup<ClassNamePair, Field> buildFieldLookup() {
        return new CachedLookup<>(
                new FieldLookup(),
                new SimpleLRUCache<ClassNamePair, Future<Field>>(1000),
                executorService
        );
    }

    private static Lookup<ClassNamePair, Method> buildPropertyGetterLookup() {
        return new CachedLookup<>(
                new PropertyGetterLookup(),
                new SimpleLRUCache<ClassNamePair, Future<Method>>(1000),
                executorService
        );
    }

    public static Field getField(Class<?> cls, String name) {
        return fieldLookup.find(new ClassNamePair(cls, name));
    }

    public static Method getGetter(Class<?> cls, String name) {
        return propertyGetterLookup.find(new ClassNamePair(cls, name));
    }

    public static Object get(Object object, String name)
            throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Method getter = propertyGetterLookup.find(new ClassNamePair(object.getClass(), name));
        if (getter != null) {
            return getter.invoke(object);
        }
        throw new NoSuchMethodException("Could not find getter for " +
                object.getClass().getName() + "." + name);
    }

    public static void set(Object object, String name, Object... value)
            throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        StringBuilder setter = new StringBuilder("set".length() + name.length());
        setter.append("set").append(name)
                .setCharAt("set".length(), Character.toUpperCase(name.charAt(0)));
        Methods.invoke(object, setter.toString(), value);
    }

    public static Object directGet(Field field, Object object) {
        try {
            if (field.isAccessible()) {
                return field.get(object);
            } else {
                field.setAccessible(true);
                Object value = field.get(object);
                field.setAccessible(false);
                return value;
            }
        } catch (IllegalAccessException e) {
            // should never reach here
            throw new RuntimeException(e);
        }
    }

    public static void directSet(Field field, Object object, Object value) {
        try {
            if (field.isAccessible()) {
                field.set(object, value);
            } else {
                field.setAccessible(true);
                field.set(object, value);
                field.setAccessible(false);
            }
        } catch (IllegalAccessException e) {
            // should never reach here
            throw new RuntimeException(e);
        }
    }
}

3. [文件] FieldLookup.java ~ 1KB     下载(15)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import canghailan.util.Lookup;

import java.lang.reflect.Field;

/**
 * @author canghailan 2012-02-23 20:31
 */
public class FieldLookup implements Lookup<ClassNamePair, Field> {
    @Override
    public Field find(ClassNamePair key) {
        Field field = getDeclaredField(key.getClazz(), key.getName());
        if (field == null) {
            field = getInheritedFromInterfaces(key.getClazz(), key.getName());
            if (field == null) {
                field = getInheritedFromSuperclass(key.getClazz(), key.getName());
            }
        }
        return field;
    }

    private static Field getDeclaredField(Class<?> cls, String name) {
        for (Field field : cls.getDeclaredFields()) {
            if (field.getName().equals(name)) {
                return field;
            }
        }
        return null;
    }

    private static Field getInheritedFromInterfaces(Class<?> cls, String name) {
        for (Class<?> i : cls.getInterfaces()) {
            Field field = getDeclaredField(i, name);
            if (field != null) {
                return field;
            }
        }
        return null;
    }

    private static Field getInheritedFromSuperclass(Class<?> cls, String name) {
        for (Class<?> s = cls.getSuperclass(); s != null; s = s.getSuperclass()) {
            Field field = getDeclaredField(s, name);
            if (field != null) {
                return field;
            }
        }
        return null;
    }
}

4. [文件] MethodLookup.java ~ 2KB     下载(13)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import canghailan.util.Lookup;

import java.lang.reflect.Method;

/**
 * @author canghailan 2012-04-19 22:21
 */
public class MethodLookup implements Lookup<MethodIdentifier, Method> {
    private final Lookup<ClassNamePair, MethodSignature[]> overloadingLookup;

    public MethodLookup(Lookup<ClassNamePair, MethodSignature[]> overloadingLookup) {
        this.overloadingLookup = overloadingLookup;
    }

    @Override
    public Method find(MethodIdentifier key) {
        MethodSignature signature = determine(findOverloading(key), key);
        return signature == null ? null : signature.getMethod();
    }

    private MethodSignature[] findOverloading(MethodIdentifier id) {
        return overloadingLookup.find(new ClassNamePair(id.getClazz(), id.getName()));
    }

    private static MethodSignature determine(MethodSignature[] overloading, MethodIdentifier id) {
        MethodSignatureDeterminer determiner = new MethodSignatureDeterminer();
        for (int index = maxAcceptIndex(overloading, id); index >= 0; --index) {
            determiner.accept(overloading[index], id);
            if (determiner.getCurrentPhase() == MethodSignatureDeterminer.Phase.FINISH) {
                break;
            }
        }
        return determiner.getMostSpecific();
    }

    private static int maxAcceptIndex(MethodSignature[] methods, MethodIdentifier id) {
        int argsLength = id.getArgumentTypes().length;
        // binary search
        int from = 0;
        int to = methods.length - 1;
        while (from <= to) {
            int index = (from + to) >>> 1;

            if (methods[index].getParameterTypes().length > argsLength) {
                to = index - 1;
            } else {
                if (index == methods.length - 1 ||
                        methods[index + 1].getParameterTypes().length > argsLength) {
                    return index;
                } else {
                    from = index + 1;
                }
            }
        }
        return -1;
    }
}

5. [文件] OverloadingLookup.java ~ 2KB     下载(14)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import canghailan.util.Lookup;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

/**
 * overloading methods and sorted by parameter length
 *
 * @author canghailan 2012-04-10 21:02
 */
public class OverloadingLookup implements Lookup<ClassNamePair, MethodSignature[]> {
    public static final Comparator<MethodSignature> PARAM_LENGTH_COMPARATOR =
            new Comparator<MethodSignature>() {
                @Override
                public int compare(MethodSignature o1, MethodSignature o2) {
                    // 按参数长度、是否变元排序,较长、定元较大,便于搜索
                    int c1 = Integer.compare(
                            o1.getParameterTypes().length,
                            o2.getParameterTypes().length
                    );
                    if (c1 == 0) {
                        if (o1.isVarArgs()) {
                            return o2.isVarArgs() ? 0 : -1;
                        } else {
                            return o2.isVarArgs() ? 1 : 0;
                        }
                    } else {
                        return c1;
                    }
                }
            };

    @Override
    public MethodSignature[] find(ClassNamePair key) {
        return sort(filter(key.getClazz(), key.getName()));
    }

    private static MethodSignature[] filter(Class<?> cls, String name) {
        List<MethodSignature> overloadingMethods = new LinkedList<>();
        for (Method method : cls.getMethods()) {
            if (method.getName().equals(name)) {
                overloadingMethods.add(new MethodSignature(method));
            }
        }
        return overloadingMethods.toArray(new MethodSignature[overloadingMethods.size()]);
    }

    private static MethodSignature[] sort(MethodSignature[] overloadingMethods) {
        Arrays.sort(overloadingMethods, PARAM_LENGTH_COMPARATOR);
        return overloadingMethods;
    }
}

6. [文件] PropertyGetterLookup.java ~ 2KB     下载(13)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import canghailan.util.Lookup;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

/**
 * @author canghailan 2012-04-10 20:19
 */
public class PropertyGetterLookup implements Lookup<ClassNamePair, Method> {
    @Override
    public Method find(ClassNamePair key) {
        return filterAndChoose(key.getClazz().getMethods(), getterNames(key.getName()));
    }

    private static Method filterAndChoose(Method[] methods, List<String> names) {
        Method getter = null;
        int nameIndex = -1;
        for (Method method : methods) {
            int theIndex = names.indexOf(method.getName());
            if (theIndex >= 0 && method.getParameterTypes().length == 0) {
                if (theIndex == 0) {
                    return method;
                } else {
                    if (getter == null || theIndex < nameIndex) {
                        getter = method;
                        nameIndex = theIndex;
                    }
                }
            }
        }
        return getter;
    }

    private static List<String> getterNames(String name) {
        StringBuilder buffer = new StringBuilder(3 + name.length());

        buffer.append("get").append(name)
                .setCharAt("get".length(), Character.toUpperCase(name.charAt(0)));
        String get = buffer.toString();

        buffer.setLength(0);
        buffer.append("is").append(name)
                .setCharAt("is".length(), Character.toUpperCase(name.charAt(0)));
        String is = buffer.toString();

        return Arrays.asList(get, is, name);
    }
}

7. [文件] Lookup.java ~ 126B     下载(14)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.util;

/**
 * @author canghailan 2012-04-10 18:34
 */
public interface Lookup<K, V> {
    V find(K key);
}

8. [文件] ClassNamePair.java ~ 899B     下载(15)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

/**
 * @author canghailan 2012-04-10 19:54
 */
public class ClassNamePair {
    private final Class<?> clazz;
    private final String name;

    public ClassNamePair(Class<?> clazz, String name) {
        assert clazz != null;
        assert name != null;
        this.clazz = clazz;
        this.name = name;
    }

    public Class<?> getClazz() {
        return clazz;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        ClassNamePair that = (ClassNamePair) o;

        return clazz == that.clazz && name.equals(that.name);
    }

    @Override
    public int hashCode() {
        return clazz.hashCode() * 31 + name.hashCode();
    }
}

9. [文件] MethodIdentifier.java ~ 739B     下载(14)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import java.util.Arrays;

/**
 * @author canghailan 2012-04-19 22:19
 */
public class MethodIdentifier {
    private final Class<?> clazz;
    private final String name;
    private final Class<?>[] argumentTypes;

    public MethodIdentifier(Class<?> clazz, String name, Class<?>[] argumentTypes) {
        this.clazz = clazz;
        this.name = name;
        this.argumentTypes = argumentTypes;
    }

    public Class<?> getClazz() {
        return clazz;
    }

    public String getName() {
        return name;
    }

    public Class<?>[] getArgumentTypes() {
        return argumentTypes;
    }

    @Override
    public String toString() {
        return Arrays.toString(argumentTypes);
    }
}

10. [文件] MethodSignature.java ~ 903B     下载(13)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import java.lang.reflect.Method;

/**
 * @author canghailan 2012-04-19 20:03
 */
public class MethodSignature {
    private final Method method;
    private final Class<?>[] parameterTypes;
    private final Class<?> varArgType;

    public MethodSignature(Method method) {
        this.method = method;
        parameterTypes = method.getParameterTypes();
        varArgType = method.isVarArgs() ?
                parameterTypes[parameterTypes.length - 1].getComponentType() : null;
    }

    public Method getMethod() {
        return method;
    }

    public Class<?>[] getParameterTypes() {
        return parameterTypes;
    }

    public boolean isVarArgs() {
        return varArgType != null;
    }

    public Class<?> getVarArgType() {
        return varArgType;
    }

    @Override
    public String toString() {
        return method.toString();
    }
}

11. [文件] MethodInvocationConversion.java ~ 3KB     下载(14)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

/**
 * @author canghailan 2012-04-21 22:54
 */
public class MethodInvocationConversion {
    public static boolean isWideningPrimitiveConversion(Class<?> from, Class<?> to) {
        if (to == int.class) {
            return from == char.class ||
                    from == short.class ||
                    from == byte.class;
        }
        if (to == double.class) {
            return from == float.class ||
                    from == long.class ||
                    from == int.class ||
                    from == char.class ||
                    from == short.class ||
                    from == byte.class;
        }
        if (to == short.class) {
            return from == byte.class;
        }
        if (to == long.class) {
            return from == int.class ||
                    from == char.class ||
                    from == short.class ||
                    from == byte.class;
        }
        if (to == float.class) {
            return from == long.class ||
                    from == int.class ||
                    from == char.class ||
                    from == short.class ||
                    from == byte.class;
        }
        return false;
    }

    public static boolean isWideningReferenceConversion(Class<?> from, Class<?> to) {
        return to.isAssignableFrom(from);
    }

    public static Class<?> boxing(Class<?> cls) {
        if (cls == int.class) {
            return Integer.class;
        }
        if (cls == double.class) {
            return Double.class;
        }
        if (cls == boolean.class) {
            return Boolean.class;
        }
        if (cls == byte.class) {
            return Byte.class;
        }
        if (cls == char.class) {
            return Character.class;
        }
        if (cls == short.class) {
            return Short.class;
        }
        if (cls == long.class) {
            return Long.class;
        }
        if (cls == float.class) {
            return Float.class;
        }
        return null;
    }

    public static Class<?> unboxing(Class<?> cls) {
        if (cls == Integer.class) {
            return int.class;
        }
        if (cls == Double.class) {
            return double.class;
        }
        if (cls == Boolean.class) {
            return boolean.class;
        }
        if (cls == Byte.class) {
            return byte.class;
        }
        if (cls == Character.class) {
            return char.class;
        }
        if (cls == Short.class) {
            return short.class;
        }
        if (cls == Long.class) {
            return long.class;
        }
        if (cls == Float.class) {
            return float.class;
        }
        return null;
    }
}

12. [文件] MethodSignatureDeterminer.java ~ 12KB     下载(16)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.lang.reflect;

import static canghailan.lang.reflect.MethodInvocationConversion.*;

/**
 * @author canghailan 2012-04-21 21:47
 */
public class MethodSignatureDeterminer {
    private Phase currentPhase;
    private MethodSignature mostSpecific;

    public MethodSignatureDeterminer() {
        this.currentPhase = Phase.START;
    }

    public Phase getCurrentPhase() {
        return currentPhase;
    }

    public MethodSignature getMostSpecific() {
        return mostSpecific;
    }

    public void accept(MethodSignature signature, MethodIdentifier id) {
//        Phase bp = currentPhase;
//        MethodSignature bms = mostSpecific;
        currentPhase.accept(this, signature, id);
//        Phase ap = currentPhase;
//        MethodSignature ams = mostSpecific;
//        System.out.print("accept: " + signature.getMethod());
//        System.out.println(" <= (" + id + ")");
//        System.out.println(bms + " => " + ams);
//        System.out.println(bp + " => " + ap);
//        System.out.println();
    }

    /**
     * <ul>
     * <li>Phase 1: Identify Matching Arity Methods Applicable by Subtyping</li>
     * <li>Phase 2: Identify Matching Arity Methods Applicable by Method Invocation Conversion</li>
     * <li>Phase 3: Identify Applicable Variable Arity Methods</li>
     * </ul>
     */
    public static enum Phase {
        START {
            @Override
            final void accept(MethodSignatureDeterminer determiner,
                              MethodSignature signature, MethodIdentifier id) {
                if (isMatchingArity(signature, id)) {
                    ApplicableKind kind = checkApplicableMatchingArity(signature, id);
                    if (kind != null) {
                        determiner.mostSpecific = signature;
                        switch (kind) {
                            case MATCHING: {
                                determiner.currentPhase = FINISH;
                                break;
                            }
                            case SUBTYPING: {
                                determiner.currentPhase = MATCHING_ARITY_BY_SUBTYPING;
                                break;
                            }
                            case METHOD_INVOCATION_CONVERSION: {
                                determiner.currentPhase = MATCHING_ARITY_BY_CONVERSION;
                                break;
                            }
                        }
                    }
                } else if (isVariableArity(signature, id)) {
                    if (checkApplicableVariableArity(signature, id) != null) {
                        determiner.mostSpecific = signature;
                        determiner.currentPhase = VARIABLE_ARITY;
                    }
                }
            }
        },
        MATCHING_ARITY_BY_SUBTYPING {
            @Override
            final void accept(MethodSignatureDeterminer determiner,
                              MethodSignature signature, MethodIdentifier id) {
                if (isMatchingArity(signature, id)) {
                    ApplicableKind kind = checkApplicableMatchingArity(signature, id);
                    if (kind != null) {
                        switch (kind) {
                            case MATCHING: {
                                determiner.mostSpecific = signature;
                                determiner.currentPhase = FINISH;
                                break;
                            }
                            case SUBTYPING: {
                                if (isMoreSpecificFixArity(signature, determiner.mostSpecific)) {
                                    determiner.mostSpecific = signature;
                                }
                                break;
                            }
                        }
                    }
                } else {
                    if (signature.getParameterTypes().length != id.getArgumentTypes().length) {
                        determiner.currentPhase = FINISH;
                    }
                }
            }
        },
        MATCHING_ARITY_BY_CONVERSION {
            @Override
            final void accept(MethodSignatureDeterminer determiner,
                              MethodSignature signature, MethodIdentifier id) {
                if (isMatchingArity(signature, id)) {
                    ApplicableKind kind = checkApplicableMatchingArity(signature, id);
                    if (kind != null) {
                        switch (kind) {
                            case MATCHING: {
                                determiner.mostSpecific = signature;
                                determiner.currentPhase = FINISH;
                                break;
                            }
                            case SUBTYPING: {
                                determiner.mostSpecific = signature;
                                determiner.currentPhase = MATCHING_ARITY_BY_SUBTYPING;
                                break;
                            }
                            case METHOD_INVOCATION_CONVERSION: {
                                if (isMoreSpecificFixArity(signature, determiner.mostSpecific)) {
                                    determiner.mostSpecific = signature;
                                }
                                break;
                            }
                        }
                    }
                } else {
                    if (signature.getParameterTypes().length != id.getArgumentTypes().length) {
                        determiner.currentPhase = FINISH;
                    }
                }
            }
        },
        VARIABLE_ARITY {
            @Override
            final void accept(MethodSignatureDeterminer determiner,
                              MethodSignature signature, MethodIdentifier id) {
                if (isVariableArity(signature, id)) {
                    if (checkApplicableVariableArity(signature, id) != null) {
                        if (isMoreSpecificVariableArity(signature, determiner.mostSpecific)) {
                            determiner.mostSpecific = signature;
                        }
                    }
                }
            }
        },
        FINISH {
            @Override
            final void accept(MethodSignatureDeterminer determiner,
                              MethodSignature signature, MethodIdentifier id) {
                //do nothing
            }
        };

        abstract void accept(MethodSignatureDeterminer determiner,
                             MethodSignature signature, MethodIdentifier id);
    }

    private static boolean isMatchingArity(MethodSignature signature, MethodIdentifier id) {
        return !signature.isVarArgs() &&
                signature.getParameterTypes().length == id.getArgumentTypes().length;
    }

    private static boolean isVariableArity(MethodSignature signature, MethodIdentifier id) {
        return signature.isVarArgs() &&
                signature.getParameterTypes().length <= id.getArgumentTypes().length;
    }

    private static boolean isMoreSpecificFixArity(MethodSignature m1, MethodSignature m2) {
        final Class<?>[] paramTypes1 = m1.getParameterTypes();
        final Class<?>[] paramTypes2 = m2.getParameterTypes();
        for (int i = 0; i < paramTypes1.length; ++i) {
            if (checkApplicable(paramTypes1[i], paramTypes2[i]) == null) {
                return false;
            }
        }
        return true;
    }

    private static boolean isMoreSpecificVariableArity(MethodSignature m1, MethodSignature m2) {
        final Class<?>[] paramTypes1 = m1.getParameterTypes();
        final int paramsLength1 = paramTypes1.length;
        final Class<?>[] paramTypes2 = m2.getParameterTypes();
        final int paramsLength2 = paramTypes2.length;
        if (paramsLength1 >= paramsLength2) {
            for (int i = 0; i < paramsLength2 - 1; ++i) {
                if (checkApplicable(paramTypes1[i], paramTypes2[i]) == null) {
                    return false;
                }
            }
            Class<?> varArgType = m2.getVarArgType();
            for (int i = paramsLength2 - 1; i < paramsLength1; ++i) {
                if (checkApplicable(paramTypes1[i], varArgType) == null) {
                    return false;
                }
            }
            return true;
        } else {
            for (int i = 0; i < paramsLength1 - 1; ++i) {
                if (checkApplicable(paramTypes1[i], paramTypes2[i]) == null) {
                    return false;
                }
            }
            Class<?> varArgType = m1.getVarArgType();
            for (int i = paramsLength1 - 1; i < paramsLength2; ++i) {
                if (checkApplicable(varArgType, paramTypes2[i]) == null) {
                    return false;
                }
            }
            return true;
        }
    }

    private static ApplicableKind checkApplicableMatchingArity(MethodSignature method,
                                                               MethodIdentifier id) {
        if (method.getParameterTypes().length == 0) {
            return ApplicableKind.MATCHING;
        } else {
            ApplicableKind kind = null;
            final Class<?>[] paramTypes = method.getParameterTypes();
            final Class<?>[] argTypes = id.getArgumentTypes();
            for (int i = 0; i < paramTypes.length; ++i) {
                ApplicableKind paramKind = checkApplicable(argTypes[i], paramTypes[i]);
                if (paramKind == null) {
                    return null;
                }
                kind = kind == null ? paramKind : kind.combine(paramKind);
            }
            return kind;
        }
    }

    private static ApplicableKind checkApplicableVariableArity(MethodSignature method,
                                                               MethodIdentifier id) {
        ApplicableKind kind = null;
        final Class<?>[] paramTypes = method.getParameterTypes();
        final int paramsLength = paramTypes.length;
        final Class<?>[] argTypes = id.getArgumentTypes();
        final int argsLength = argTypes.length;
        for (int i = 0; i < paramsLength - 1; ++i) {
            ApplicableKind paramKind = checkApplicable(argTypes[i], paramTypes[i]);
            if (paramKind == null) {
                return null;
            }
            kind = kind == null ? paramKind : kind.combine(paramKind);
        }
        Class<?> varArgType = method.getVarArgType();
        for (int i = paramsLength - 1; i < argsLength; ++i) {
            ApplicableKind paramKind = checkApplicable(argTypes[i], varArgType);
            if (paramKind == null) {
                return null;
            }
            kind = kind == null ? paramKind : kind.combine(paramKind);
        }
        return kind;
    }

    private static ApplicableKind checkApplicable(Class<?> from, Class<?> to) {
        if (to == from) {
            return ApplicableKind.MATCHING;
        }
        if (to.isPrimitive()) {
            if (from == null) {
                return null;
            }
            if (from.isPrimitive()) {
                return isWideningPrimitiveConversion(from, to) ?
                        ApplicableKind.SUBTYPING : null;
            } else {
                Class<?> unboxingClass = unboxing(from);
                return (to == unboxingClass || isWideningPrimitiveConversion(unboxingClass, to)) ?
                        ApplicableKind.METHOD_INVOCATION_CONVERSION : null;
            }
        } else {
            if (from == null) {
                return ApplicableKind.SUBTYPING;
            }
            if (from.isPrimitive()) {
                Class<?> boxingClass = boxing(from);
                return (to == boxingClass || isWideningReferenceConversion(boxingClass, to)) ?
                        ApplicableKind.METHOD_INVOCATION_CONVERSION : null;
            } else {
                return isWideningReferenceConversion(from, to) ?
                        ApplicableKind.SUBTYPING : null;
            }
        }
    }

    static enum ApplicableKind {
        MATCHING,
        SUBTYPING,
        METHOD_INVOCATION_CONVERSION;

        ApplicableKind combine(ApplicableKind that) {
            return this.compareTo(that) > 0 ? this : that;
        }
    }
}

13. [文件] CachedLookup.java ~ 1KB     下载(13)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.util;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @author canghailan 2012-03-12 18:57
 */
public class CachedLookup<K, V> implements Lookup<K, V> {
    private final Lookup<K, V> lookup;
    private final Map<K, Future<V>> cache;
    private final ExecutorService executorService;

    public CachedLookup(Lookup<K, V> lookup, Map<K, Future<V>> cache, ExecutorService executorService) {
        this.lookup = lookup;
        this.cache = cache;
        this.executorService = executorService;
    }

    @Override
    public V find(final K key) {
        Future<V> value = cache.get(key);
        if (value == null) {
            synchronized (cache) {
                value = cache.get(key);
                if (value == null) {
                    value = executorService.submit(new Callable<V>() {
                        @Override
                        public V call() throws Exception {
                            return lookup.find(key);
                        }
                    });
                    cache.put(key, value);
                }
            }
        }
        try {
            return value.get();
        } catch (Exception e) {
            return lookup.find(key);
        }
    }
}

14. [文件] SimpleLRUCache.java ~ 604B     下载(13)     跳至 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [全屏预览]

package canghailan.util;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author canghailan 2012-04-18 18:09
 */
public class SimpleLRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int threshold;

    public SimpleLRUCache(int threshold) {
        this(threshold, 0.75f);
    }

    public SimpleLRUCache(int threshold, float loadFactor) {
        super((int) (threshold / loadFactor) + 1, loadFactor, true);
        this.threshold = threshold;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > threshold;
    }
}


开源中国-程序员在线工具:Git代码托管 API文档大全(120+) JS在线编辑演示 二维码 更多»

发表评论 回到顶部 网友评论(3)

  • 1楼:空指针 发表于 2012-05-05 07:49 回复此评论
    老兄的代码没注释啊!
  • 2楼:whaon 发表于 2012-05-05 10:19 回复此评论
    有什么用
  • 3楼:dizh 发表于 2013-01-15 16:43 回复此评论
    是javaeye上的Redafx么????
开源从代码分享开始 分享代码
canghailan的其它代码 全部(15)...