Class XReflect


  • public final class XReflect
    extends Object
    Provides additional generic util methods for working with java reflection.
    • Constructor Detail

      • XReflect

        public XReflect()
    • Method Detail

      • setAccessible

        public static final Field setAccessible​(Class<?> actualClass,
                                                Field field)
      • isInstanceField

        public static final boolean isInstanceField​(Field field)
      • toFieldName

        public static final String toFieldName​(Field field)
      • isInterfaceOfType

        public static final boolean isInterfaceOfType​(Class<?> interfaceClass,
                                                      Class<?> implementedSuperInterface)
      • implementsInterface

        public static final boolean implementsInterface​(Class<?> c,
                                                        Class<?> interfaceClass)
      • getClassHierarchyInterfaces

        public static final Class<?>[] getClassHierarchyInterfaces​(Class<?> classClass)
      • isOfClassType

        public static final boolean isOfClassType​(Class<?> c,
                                                  Class<?> superclass)
      • isSubClassOf

        public static final boolean isSubClassOf​(Class<?> c,
                                                 Class<?> superclass)
      • isEnum

        public static boolean isEnum​(Class<?> c)
        Utility method fixing the WRONGLY implemented Class.isEnum().

        Their description is weird ("if this class was declared as an enum in the source code") and the implemented behavior is dangerous and useless to identify all classes of instances that are enums.

        For enum anonymous inner class instances (writing { ... } behind an enum constant), Class.isEnum()returns false on the generated type. That is a bug since the type is still an enum, a sub class of Enum. So the correct way of testing a class for being an enum is using java.lang.Enum.class.isAssignableFrom(...). This method does that.

        Parameters:
        c - the Class to be tested.
        Returns:
        whether the passed Class is a sub class of Enum, i.e. an enum.
      • isDeclaredEnum

        public static boolean isDeclaredEnum​(Class<?> c)
      • isSubEnum

        public static boolean isSubEnum​(Class<?> c)
      • getDeclaredEnumClass

        public static Class<?> getDeclaredEnumClass​(Class<?> c)
      • resolveEnumConstantInstance

        public static Object resolveEnumConstantInstance​(Class<?> type,
                                                         int ordinal)
      • resolveEnumConstantInstanceTyped

        public static <T> T resolveEnumConstantInstanceTyped​(Class<T> type,
                                                             int ordinal)
      • validateIsEnum

        public static <T> Class<T> validateIsEnum​(Class<T> type)
      • iterateDeclaredFieldsUpwards

        public static final <L extends Consumer<Field>> L iterateDeclaredFieldsUpwards​(Class<?> startingClass,
                                                                                       L logic)
        Alias for iterateDeclaredFieldsUpwards(startingClass, Object.class, logic).
        Type Parameters:
        L - The logic's contextual type.
        Parameters:
        startingClass - the class whose fields shall be iterated.
        logic - the Consumer to be executed on each field.
        Returns:
        the passed logic.
      • iterateDeclaredFieldsUpwards

        public static final <L extends Consumer<Field>> L iterateDeclaredFieldsUpwards​(Class<?> startingClass,
                                                                                       Class<?> boundingClass,
                                                                                       L logic)
        Iterates over every declared field of all classes upwards starting at startingClassuntil class boundingClass is reached and executes the passed Consumer on it.

        The declared fields of each class are iterated in reverse order (from index Class.getDeclaredFields().length - 1 to index 0 ).

        This method is useful to maintain the natural declaration order of the fields, iterating from the last declared field of the lowest class (the passed class itself) to the first declared field of the highest class declaring a field.

        Type Parameters:
        L - The logic's contextual type.
        Parameters:
        startingClass - the class whose fields shall be iterated.
        boundingClass - the class in the hierarchy at which to stop iterating, exclusive bound.
        logic - the Consumer to be executed on each field.
        Returns:
        the passed logic.
      • iterateAllClassMethods

        public static final <C extends Consumer<? super Method>> C iterateAllClassMethods​(Class<?> clazz,
                                                                                          C logic)
      • iterateAllClassMethods

        public static final <C extends Consumer<? super Method>> C iterateAllClassMethods​(Class<?> clazz,
                                                                                          Class<?> bound,
                                                                                          C logic)
      • isFinal

        public static final boolean isFinal​(Field field)
      • isStatic

        public static final boolean isStatic​(Field field)
      • isSynthetic

        public static final boolean isSynthetic​(Field field)
      • isStaticFinal

        public static final boolean isStaticFinal​(Field field)
      • isPrimitive

        public static final boolean isPrimitive​(Field field)
      • isReference

        public static final boolean isReference​(Field field)
      • isTransient

        public static final boolean isTransient​(Field field)
      • isNotTransient

        public static final boolean isNotTransient​(Field field)
      • isPrivate

        public static final boolean isPrivate​(Field field)
      • isProtected

        public static final boolean isProtected​(Field field)
      • isPublic

        public static final boolean isPublic​(Field field)
      • isDefaultVisible

        public static final boolean isDefaultVisible​(Field field)
      • isAbstract

        public static final boolean isAbstract​(Class<?> type)
      • isAbstract

        public static final boolean isAbstract​(Method method)
      • getFieldValue

        public static final Object getFieldValue​(Field field,
                                                 Object obj)
        Calls Field.get(Object) and wraps the moronic abstraction-destroying checkedIllegalAccessException with a proper IllegalAccessRuntimeException.
        Parameters:
        field - the field from which the value shall be extracted.
        obj - object from which the represented field's value is to be extracted
        Returns:
        the value of the represented field in object obj; primitive values are wrapped in an appropriate object before being returned
      • resolveType

        public static final Class<?> resolveType​(String typeName)
                                          throws LinkageError,
                                                 ExceptionInInitializerError,
                                                 ClassNotFoundException
        Resolves the passed type name to a runtime type (instance of type Class). In contrary to Class.forName(String), this method can resolve primitive type names, as well.

        Note on naming:
        1.) Looking up a runtime type instance for a type name string is best described as "resolving" the type.
        2.) The things that are resolved are TYPES (classes, interfaces, arrays and in later Java versions enums and annotations), not just classes. That the java inventors seemingly didn't understand their own type system and just called everything "Class" on the API-level,* even interfaces, is just an error that should be repeated as less as possible.
        In conclusion, the proper naming for the action executed by this method (meaning a verb) is "resolveType" and not a dilettantish "forName" as in Class.forName(String).

        Parameters:
        typeName - the type name to be resolved, primitive name or full qualified type name.
        Returns:
        the resolved type instance (of type Class)
        Throws:
        LinkageError - see Class.forName(String)
        ExceptionInInitializerError - see Class.forName(String)
        ClassNotFoundException - see Class.forName(String)
      • tryResolveType

        public static final Class<?> tryResolveType​(String className)
        Calls resolveType(String), but suppresses any ClassNotFoundException and returnsnull instead. This is useful if the passed class name is only potentially resolvable at runtime and is still valid if not. Example: resolving a old type dictionary as far as possible and marking the not resolvable types as unresolvable.
        Parameters:
        className -
        Returns:
        the Class instance representing the passed class name or null if unresolevable.
      • tryIterativeResolveType

        public static final Class<?> tryIterativeResolveType​(String... typeNames)
        This methods attempts to resolve the passed typeNames to Class instances usingClass.forName(String) one by one. The Class instance of the first successful attempt is returned. If none of the passed typeNames can be resolved, null is returned. See iterativeResolveType(String...) for an exception-throwing version.

        Note:
        While it is generally a bad idea to just use a trial and error approach until something works, a logic like this is required to resolve types whose packages changes accross different versions of a library. If the different full qualified class names are known, they can be used in an iterative attempt to resolve the class, hence avoiding hard dependencies to certain library versions in the using code by moving type names from imports at compile time to dynamic class resolving at runtime.
        However, this approach has its limits, of course. If too much changes (field names, method names, parameters, behavior) the dynamic strategy results in chaos as the compiler gets more and more circumvented and more and more source code is transformed into contextless plain strings.
        Therefore, when in doubt, it is preferable to stick to the general notion of this method being a "bad idea" and finding a more reliable solution.

        Parameters:
        typeNames - the full qualified type names to be attempted to be resolved one by one.
        Returns:
        the first successfully resolved Class instance or null
        See Also:
        Class.forName(String)
      • tryGetDeclaredField

        public static final Field tryGetDeclaredField​(Class<?> declaringClass,
                                                      String fieldName)
      • tryResolvePrimitiveType

        public static final Class<?> tryResolvePrimitiveType​(String className)
      • isPrimitiveTypeName

        public static boolean isPrimitiveTypeName​(String typeName)
      • isOfAnyType

        public static final boolean isOfAnyType​(Class<?> subject,
                                                Class<?>... supertypes)
      • isOfAnyType

        public static final boolean isOfAnyType​(Class<?> subject,
                                                Iterable<Class<?>> supertypes)
      • getClass

        public static <T> Class<T> getClass​(T object)
        *sigh
        Parameters:
        object -
      • fieldIdentifierDelimiter

        public static char fieldIdentifierDelimiter()
      • typename_enum

        public static String typename_enum()
      • nestedClassNameSeparator

        public static char nestedClassNameSeparator()
      • toFullQualifiedFieldName

        public static String toFullQualifiedFieldName​(Class<?> actualClass,
                                                      Field field)
      • deriveFieldIdentifier

        public static String deriveFieldIdentifier​(Field field)
      • toFullQualifiedFieldName

        public static String toFullQualifiedFieldName​(Class<?> c,
                                                      String fieldName)
      • getFieldIdentifierDelimiterIndex

        public static int getFieldIdentifierDelimiterIndex​(String identifier)
      • getFieldIdentifierClassName

        public static String getFieldIdentifierClassName​(String fieldIdentifier)
      • getFieldIdentifierFieldName

        public static String getFieldIdentifierFieldName​(String fieldIdentifier)
      • validateInterfaceType

        public static <A> Class<A> validateInterfaceType​(Class<A> type)
      • validateNonInterfaceType

        public static <A> Class<A> validateNonInterfaceType​(Class<A> type)
      • validateNonArrayType

        public static <A> Class<A> validateNonArrayType​(Class<A> type)
      • validateArrayType

        public static <A> Class<A> validateArrayType​(Class<A> arrayType)
      • validatePrimitiveType

        public static <A> Class<A> validatePrimitiveType​(Class<A> primitiveType)
      • validateNonPrimitiveType

        public static <A> Class<A> validateNonPrimitiveType​(Class<A> primitiveType)
      • isJavaUtilCollectionType

        public static boolean isJavaUtilCollectionType​(Class<?> type)
        Checks if the passed type is equal to or a sub type of Collection or Map.

        Sad that such a method is necessary in the first place, but here we are.
        (See XMap for an example on how to do it correctly.)

        Parameters:
        type - the type to be checked.
        Returns:
        whether or not the passed type is a java.util collection "in the broader sense".
        See Also:
        Collection, Map
      • hasEnumeratedTypeName

        public static boolean hasEnumeratedTypeName​(Class<?> type)
      • isProxyClass

        public static boolean isProxyClass​(Class<?> c)
      • isValidProxyClass

        public static boolean isValidProxyClass​(Class<?> c)
      • collectPrimitiveFieldsByByteSize

        public static Field[] collectPrimitiveFieldsByByteSize​(Field[] fields,
                                                               int byteSize)
      • collectInstanceFields

        public static final Field[] collectInstanceFields​(Class<?> objectClass)
      • collectInstanceFields

        public static final Field[] collectInstanceFields​(Class<?> objectClass,
                                                          Predicate<? super Field> selector)
      • calculatePrimitivesLength

        public static int calculatePrimitivesLength​(Field[] primFields)