java Reflection.java

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java Reflection.java相关的知识,希望对你有一定的参考价值。

/**
* * An utility class that simplifies reflection in Bukkit plugins. * * @author
* Kristian -
* https://github.com/dmulloy2/ProtocolLib/blob/master/Examples/TinyProtocol
* /src/main/java/com/comphenix/tinyprotocol/Reflection.java
*/
public final class Reflection {

    public interface ConstructorInvoker {
        public Object invoke(Object... arguments);
    }

    public interface MethodInvoker {
        public Object invoke(Object target, Object... arguments);
    }

    public interface FieldAccessor<T> {
        public T get(Object target);

        public void set(Object target, Object value);

        public boolean hasField(Object target);
    }

    private static String OBC_PREFIX = Bukkit.getServer().getClass()
            .getPackage().getName();
    private static String NMS_PREFIX = OBC_PREFIX.replace(
            "org.bukkit.craftbukkit", "net.minecraft.server");
    private static String VERSION = OBC_PREFIX.replace(
            "org.bukkit.craftbukkit", "").replace(".", "");
    private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}");

    private Reflection() {
    }

    public static <T> FieldAccessor<T> getField(Class<?> target, String name,
                                                Class<T> fieldType) {
        return getField(target, name, fieldType, 0);
    }

    public static <T> FieldAccessor<T> getField(String className, String name,
                                                Class<T> fieldType) {
        return getField(getClass(className), name, fieldType, 0);
    }

    public static <T> FieldAccessor<T> getField(Class<?> target,
                                                Class<T> fieldType, int index) {
        return getField(target, null, fieldType, index);
    }

    public static <T> FieldAccessor<T> getField(String className,
                                                Class<T> fieldType, int index) {
        return getField(getClass(className), fieldType, index);
    }

    private static <T> FieldAccessor<T> getField(Class<?> target, String name,
                                                 Class<T> fieldType, int index) {
        for (final Field field : target.getDeclaredFields()) {
            if ((name == null || field.getName().equals(name))
                    && fieldType.isAssignableFrom(field.getType())
                    && index-- <= 0) {
                field.setAccessible(true);
                return new FieldAccessor<T>() {
                    @Override
                    @SuppressWarnings("unchecked")
                    public T get(Object target) {
                        try {
                            return (T) field.get(target);
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(
                                    "Cannot access reflection.", e);
                        }
                    }

                    @Override
                    public void set(Object target, Object value) {
                        try {
                            field.set(target, value);
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(
                                    "Cannot access reflection.", e);
                        }
                    }

                    @Override
                    public boolean hasField(Object target) {
                        return field.getDeclaringClass().isAssignableFrom(
                                target.getClass());
                    }
                };
            }
        }
        if (target.getSuperclass() != null)
            return getField(target.getSuperclass(), name, fieldType, index);
        throw new IllegalArgumentException("Cannot find field with type "
                + fieldType);
    }

    public static MethodInvoker getMethod(String className, String methodName,
                                          Class<?>... params) {
        return getTypedMethod(getClass(className), methodName, null, params);
    }

    public static MethodInvoker getMethod(Class<?> clazz, String methodName,
                                          Class<?>... params) {
        return getTypedMethod(clazz, methodName, null, params);
    }

    public static MethodInvoker getTypedMethod(Class<?> clazz,
                                               String methodName, Class<?> returnType, Class<?>... params) {
        for (final Method method : clazz.getDeclaredMethods()) {
            if ((methodName == null || method.getName().equals(methodName))
                    && (returnType == null)
                    || method.getReturnType().equals(returnType)
                    && Arrays.equals(method.getParameterTypes(), params)) {
                method.setAccessible(true);
                return new MethodInvoker() {
                    @Override
                    public Object invoke(Object target, Object... arguments) {
                        try {
                            return method.invoke(target, arguments);
                        } catch (Exception e) {
                            throw new RuntimeException("Cannot invoke method "
                                    + method, e);
                        }
                    }
                };
            }
        }
        if (clazz.getSuperclass() != null)
            return getMethod(clazz.getSuperclass(), methodName, params);
        throw new IllegalStateException(String.format(
                "Unable to find method %s (%s).", methodName,
                Arrays.asList(params)));
    }

    public static ConstructorInvoker getConstructor(String className,
                                                    Class<?>... params) {
        return getConstructor(getClass(className), params);
    }

    public static ConstructorInvoker getConstructor(Class<?> clazz,
                                                    Class<?>... params) {
        for (final Constructor<?> constructor : clazz.getDeclaredConstructors()) {
            if (Arrays.equals(constructor.getParameterTypes(), params)) {
                constructor.setAccessible(true);
                return new ConstructorInvoker() {
                    @Override
                    public Object invoke(Object... arguments) {
                        try {
                            return constructor.newInstance(arguments);
                        } catch (Exception e) {
                            throw new RuntimeException(
                                    "Cannot invoke constructor " + constructor,
                                    e);
                        }
                    }
                };
            }
        }
        throw new IllegalStateException(String.format(
                "Unable to find constructor for %s (%s).", clazz,
                Arrays.asList(params)));
    }

    public static Class<Object> getUntypedClass(String lookupName) {
        @SuppressWarnings({ "rawtypes", "unchecked" })
        Class<Object> clazz = (Class) getClass(lookupName);
        return clazz;
    }

    public static Class<?> getClass(String lookupName) {
        return getCanonicalClass(expandVariables(lookupName));
    }

    public static Class<?> getNewClass(String lookupName) {
        return getCanonicalClass(lookupName);
    }

    public static Class<?> getMinecraftClass(String name) {
        return getCanonicalClass(NMS_PREFIX + "." + name);
    }

    public static Class<?> getCraftBukkitClass(String name) {
        return getCanonicalClass(OBC_PREFIX + "." + name);
    }

    private static Class<?> getCanonicalClass(String canonicalName) {
        try {
            return Class.forName(canonicalName);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Cannot find " + canonicalName,
                    e);
        }
    }

    private static String expandVariables(String name) {
        StringBuffer output = new StringBuffer();
        Matcher matcher = MATCH_VARIABLE.matcher(name);
        while (matcher.find()) {
            String variable = matcher.group(1);
            String replacement = "";
            if ("nms".equalsIgnoreCase(variable))
                replacement = NMS_PREFIX;
            else if ("obc".equalsIgnoreCase(variable))
                replacement = OBC_PREFIX;
            else if ("version".equalsIgnoreCase(variable))
                replacement = VERSION;
            else
                throw new IllegalArgumentException("Unknown variable: "
                        + variable);
            if (replacement.length() > 0 && matcher.end() < name.length()
                    && name.charAt(matcher.end()) != '.')
                replacement += ".";
            matcher.appendReplacement(output,
                    Matcher.quoteReplacement(replacement));
        }
        matcher.appendTail(output);
        return output.toString();
    }
}

以上是关于java Reflection.java的主要内容,如果未能解决你的问题,请参考以下文章

java factory_with_reflection.java

Java Reflection (JAVA反射)机制详解

java反射机制

java反射

Java的基本使用之反射

2019.9.25 java小知识,反射