All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.hypfvieh.util.ReflectionUtil Maven / Gradle / Ivy

Go to download

A collection of utils commonly used in my projects. Feel free to use it (or parts of it) in your own projects.

The newest version!
package com.github.hypfvieh.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

/**
 * Utility methods which uses reflection techniques.
 *
 * @author David Michaelis ([email protected])
 * @since v1.0.1 - 2018-02-12
 */
public final class ReflectionUtil {

    private ReflectionUtil() {

    }

    /**
     * Returns a list containing {@code Method} or {@link Field} objects reflecting all the
     * declared methods/fields of the class or interface represented by this {@code
     * Class} object, including public, protected, default (package)
     * access, and private methods/fields, also including inherited methods/fields.
     *
     * @since v1.0.2 - 2018-04-20
     *
     * @param _clazz the class object to examine
     * @return the Set of {@code Method} or {@code Field} objects representing all the
     *         declared methods of this class and superclasses - Set maybe empty but never null
     */
    @SuppressWarnings("unchecked")
    static  Set getAllDeclared(Class _clazz, Class _type) {

        if (_type != Field.class && _type != Method.class) { // only fields and methods are supported
            return new LinkedHashSet<>();
        }

        Set l = new LinkedHashSet<>();
        Method method;
        try {
            if (_type == Method.class) {
                method = Class.class.getDeclaredMethod("getDeclaredMethods");
            } else {
                method = Class.class.getDeclaredMethod("getDeclaredFields");
            }

            if (_clazz != null) {
                List entriesInThisClass = Arrays.asList((T[]) method.invoke(_clazz));
                l.addAll(entriesInThisClass);

                if (_clazz.getSuperclass() != null) {
                    l.addAll(getAllDeclared(_clazz.getSuperclass(), _type));
                }

            }
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException _ex) {
            return new LinkedHashSet<>();
        }
        return l;
    }

    /**
     * Extract all {@link Field}s found in the given class recursively.
     * This means, all {@link Field}s are retrieved, even fields which only exists in superclasses.
*
* NOTE: Accessibility of {@link Field}s returned in the {@link Set} have not been changed * (setAccessable(true) is NOT called explicitly)! * * @param _class class to analyze * @param _fieldsToIgnore fields to skip * * @return null if _class was null, Set otherwise */ public static Set getAllDeclaredFields(Class _class, String... _fieldsToIgnore) { if (_class == null) { return null; } List fieldsToIgnore = Arrays.asList(_fieldsToIgnore); Set allDeclared = getAllDeclared(_class, Field.class); return allDeclared.stream() .filter(f -> !fieldsToIgnore.contains(f.getName())) .collect(Collectors.toCollection(LinkedHashSet::new)); } /** * Extract all {@link Field}s which are static and do not match any of the given ignore names. * * @param _class class to analyze * @param _fieldsToIgnore fields to skip * * @return null if _class was null, Set otherwise */ public static Set getAllDeclaredStaticFields(Class _class, String... _fieldsToIgnore) { return getAllDeclaredStatic(ReflectionType.FIELD, _class, _fieldsToIgnore); } /** * Extract all {@link Field}s which are not static and do not match any of the given ignore names. * * @param _class class to analyze * @param _fieldsToIgnore fields to skip * * @return null if _class was null, Set otherwise */ public static Set getAllDeclaredNonStaticFields(Class _class, String... _fieldsToIgnore) { return getAllDeclaredNonStatic(ReflectionType.FIELD, _class, _fieldsToIgnore); } /** * Extract all {@link Field}s with any of the given annotations found in the given class recursively. * This means, all {@link Field}s are retrieved, even fields which only exists in superclasses.
*
* NOTE: Accessibility of {@link Field}s returned in the {@link Set} have not been changed * (setAccessable(true) is NOT called explicitly)! * * @param _class class to analyze * @param _annotations annotations to check for * * @return null if _class was null, Set otherwise */ @SafeVarargs public static Set getAllDeclaredFieldsAnnotatedWithAny(Class _class, Class... _annotations) { return getAllDeclaredWithAnnotationAction(ReflectionType.FIELD, _class, (f, a) -> f.isAnnotationPresent(a), _annotations); } /** * Extract all {@link Field}s without any of the given annotations found in the given class recursively. * This means, all {@link Field}s are retrieved, even fields which only exists in superclasses.
*
* NOTE: Accessibility of {@link Field}s returned in the {@link Set} have not been changed * (setAccessable(true) is NOT called explicitly)! * * @param _class class to analyze * @param _annotations annotations to check for * * @return null if _class was null, Set otherwise */ @SafeVarargs public static Set getAllDeclaredFieldsNotAnnotatedWithAny(Class _class, Class... _annotations) { return getAllDeclaredWithAnnotationAction(ReflectionType.FIELD, _class, (f, a) -> !f.isAnnotationPresent(a), _annotations); } /** * Extract all {@link Method}s found in the given class recursively. * This means, all {@link Method}s are retrieved, even methods which only exists in superclasses.
*
* NOTE: Accessibility of {@link Method}s returned in the {@link Set} have not been changed * (setAccessable(true) is NOT called explicitly)! * * @since v1.0.2 - 2018-04-20 * * @param _class class to analyze * @param _methodsToIgnore methods to skip * * @return null if _class was null, Set otherwise */ public static Set getAllDeclaredMethods(Class _class, String... _methodsToIgnore) { if (_class == null) { return null; } List methodsToIgnore = Arrays.asList(_methodsToIgnore); Set allDeclared = getAllDeclared(_class, Method.class); return allDeclared.stream() .filter(f -> !methodsToIgnore.contains(f.getName())) .collect(Collectors.toCollection(LinkedHashSet::new)); } /** * Extract all {@link Method}s which are static and do not match any of the given ignore names. * * @since v1.0.2 - 2018-04-20 * * @param _class class to analyze * @param _methodNamesToIgnore methods to skip * * @return null if _class was null, Set otherwise */ public static Set getAllDeclaredStaticMethods(Class _class, String... _methodNamesToIgnore) { return getAllDeclaredStatic(ReflectionType.METHOD, _class, _methodNamesToIgnore); } /** * Extract all {@link Method}s which are not static and do not match any of the given ignore names. * * @since v1.0.2 - 2018-04-20 * * @param _class class to analyze * @param _methodNamesToIgnore methods to skip * * @return null if _class was null, Set otherwise */ public static Set getAllDeclaredNonStaticMethods(Class _class, String... _methodNamesToIgnore) { return getAllDeclaredNonStatic(ReflectionType.METHOD, _class, _methodNamesToIgnore); } /** * Extract all {@link Method}s with any of the given annotations found in the given class recursively. * This means, all {@link Method}s are retrieved, even fields which only exists in superclasses.
*
* NOTE: Accessibility of {@link Method}s returned in the {@link Set} have not been changed * (setAccessable(true) is NOT called explicitly)! * * @since v1.0.2 - 2018-04-20 * * @param _class class to analyze * @param _annotations annotations to check for * * @return null if _class was null, Set otherwise */ @SafeVarargs public static Set getAllDeclaredMethodsAnnotatedWithAny(Class _class, Class... _annotations) { return getAllDeclaredWithAnnotationAction(ReflectionType.METHOD, _class, (f, a) -> f.isAnnotationPresent(a), _annotations); } /** * Extract all {@link Method}s without any of the given annotations found in the given class recursively. * This means, all {@link Method}s are retrieved, even fields which only exists in superclasses.
*
* NOTE: Accessibility of {@link Method}s returned in the {@link Set} have not been changed * (setAccessable(true) is NOT called explicitly)! * * @since v1.0.2 - 2018-04-20 * * @param _class class to analyze * @param _annotations annotations to check for * * @return null if _class was null, Set otherwise */ @SafeVarargs public static Set getAllDeclaredMethodsNotAnnotatedWithAny(Class _class, Class... _annotations) { return getAllDeclaredWithAnnotationAction(ReflectionType.METHOD, _class, (f, a) -> !f.isAnnotationPresent(a), _annotations); } /** * Extract all {@link Field}s or {@link Method}s which are static and do not match any of the given ignore names. * * @since v1.0.2 - 2018-04-20 * * @param _type ReflectionType * @param _class class to analyze * @param _ignoreNames member names to ignore * @return */ private static Set getAllDeclaredStatic(ReflectionType _type, Class _class, String... _ignoreNames) { @SuppressWarnings("unchecked") Set allDeclaredFields = (Set) getAllDeclared(_class, _type.getReflectionClass()); List ignoreNames = Arrays.asList(_ignoreNames); return allDeclaredFields.stream() .filter(f -> !ignoreNames.contains(f.getName())) .filter(f -> Modifier.isStatic(f.getModifiers())) .collect(Collectors.toCollection(LinkedHashSet::new)); } /** * Extract all {@link Field}s or {@link Method}s which are not static and do not match any of the given ignore names. * * @since v1.0.2 - 2018-04-20 * * @param _type ReflectionType * @param _class class to analyze * @param _ignoreNames member names to ignore * @return */ private static Set getAllDeclaredNonStatic(ReflectionType _type, Class _class, String... _ignoreNames) { @SuppressWarnings("unchecked") Set allDeclaredFields = (Set) getAllDeclared(_class, _type.getReflectionClass()); List ignoreNames = Arrays.asList(_ignoreNames); return allDeclaredFields.stream() .filter(f -> !ignoreNames.contains(f.getName())) .filter(f -> !Modifier.isStatic(f.getModifiers())) .collect(Collectors.toCollection(LinkedHashSet::new)); } /** * Extract all {@link Field}s or {@link Method}s and validates each field/method against the given {@link BiConsumer} lambda expression. * Result will depend on lambda. All positive lambda results (test returns true), will be added to the result Set. * * @since v1.0.2 - 2018-04-20 * @param _class class to analyze * @param _annotationCheckLambda lambda to use to check every annotation * @param _annotations annotations to check for * @return null if class was null, Set otherwise */ @SafeVarargs private static Set getAllDeclaredWithAnnotationAction(ReflectionType _type, Class _class, BiPredicate> _annotationCheckLambda, Class... _annotations) { if (_class == null) { return null; } if (_annotations == null || _annotations.length == 0) { return new LinkedHashSet<>(); } @SuppressWarnings("unchecked") Set allDeclaredFields = (Set) getAllDeclared(_class, _type.getReflectionClass()); Set result = new LinkedHashSet<>(); for (T field : allDeclaredFields) { for (Class annot : _annotations) { if (_annotationCheckLambda.test(field, annot)) { result.add(field); break; } } } return result; } /** * Enum which defines which information is retrieved by reflection. * * @author hypfvieh * @since v1.0.2 - 2018-04-20 */ public static enum ReflectionType { FIELD(Field.class), METHOD(Method.class); private final Class reflectionClass; private ReflectionType(Class _class) { reflectionClass = _class; } public Class getReflectionClass() { return reflectionClass; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy