java.lang.Object
dk.cloudcreate.essentials.shared.reflection.Reflector

public final class Reflector extends Object
Caching Java Reflection helper
Encapsulates Constructors, Methods and Fields while providing high-level method for invoking constructors, method and getting/setting fields

Depending on the version of Java you're using you may need to explicitly add something like the following to your Module Config or Java arguments to ensure that Reflector is allowed to perform Java reflection
See https://docs.oracle.com/en/java/javase/17/migrate/migrating-jdk-8-later-jdk-releases.html#GUID-12F945EB-71D6-46AF-8C3D-D354FD0B1781 for more information and to understand the implications of adding the --add-opens argument.
See Also:
  • Field Details

  • Method Details

    • reflectOn

      public static Reflector reflectOn(String fullyQualifiedClassName)
      Create a Reflector instance for the class with fullyQualifiedClassName
      Parameters:
      fullyQualifiedClassName - the fully qualified class name for the type we want to reflect on
      Returns:
      the Reflector instance
    • reflectOn

      public static Reflector reflectOn(Class<?> type)
      Create a Reflector instance for the type
      Parameters:
      type - the type we want to reflect on
      Returns:
      the Reflector instance
    • hasDefaultConstructor

      public boolean hasDefaultConstructor()
      Does the type have a default no-arguments constructor?
      Returns:
      true if the type has a default no-arguments constructor, otherwise false
    • getDefaultConstructor

      public Optional<Constructor<?>> getDefaultConstructor()
      Get the default no-arguments constructor
      Returns:
      The default no-args constructor wrapped in an Optional, otherwise an Optional.empty() if no default no-args constructor exists
    • hasMatchingConstructorBasedOnArguments

      public boolean hasMatchingConstructorBasedOnArguments(Object... constructorArguments)
      Perform constructor matching based on actual argument values (as opposed to hasMatchingConstructorBasedOnParameterTypes(Class[]))
      The constructor match doesn't require exact type matches only compatible type matches
      Parameters:
      constructorArguments - the actual argument values
      Returns:
      true if there's a single matching constructor, otherwise false
    • hasMatchingConstructorBasedOnParameterTypes

      public boolean hasMatchingConstructorBasedOnParameterTypes(Class<?>... parameterTypes)
      Perform constructor matching based on exact parameter types (as opposed to hasMatchingConstructorBasedOnArguments(Object...))
      Parameters:
      parameterTypes - the parameter types
      Returns:
      true if there's a single matching constructor
    • newInstance

      public <T> T newInstance(Object... constructorArguments)
      Create a new instance of the type() using a constructor that matches the constructorArguments
      The constructor matching uses the Parameters.parameterTypesMatches(Class[], Class[], boolean) without requiring an exact parameter type match
      Type Parameters:
      T - the type of the object returned
      Parameters:
      constructorArguments - the arguments for the constructor
      Returns:
      the newly created instance
      Throws:
      ReflectionException - in case something goes wrong
    • type

      public Class<?> type()
      The type wrapped by this Reflector instance
      Returns:
      The type wrapped by this Reflector instance
    • hasMethod

      public boolean hasMethod(String methodName, boolean staticMethod, Class<?>... argumentTypes)
      Does the type wrapped by this Reflector instance have a method that matches on:
      Parameters:
      methodName - the name of the method
      staticMethod - true if the matching method MUST be a static method, otherwise it will only search instance methods
      argumentTypes - the argument types that the method must support
      Returns:
      true if the type has a matching method, otherwise false
      See Also:
    • findMatchingMethod

      public Optional<Method> findMatchingMethod(String methodName, boolean staticMethod, Class<?>... argumentTypes)
      Find the first method in the type wrapped by this Reflector instance that matches on:
      Parameters:
      methodName - the name of the method
      staticMethod - true if the matching method MUST be a static method, otherwise it will only search instance methods
      argumentTypes - the argument types that the method must support
      Returns:
      an Optional with the matching method or Optional.empty() if no matching could be made
      Throws:
      TooManyMatchingMethodsFoundException - in case there are more than 1 method that matches on the argument type
    • invokeStatic

      public <R> R invokeStatic(String methodName, Object... arguments)
      Invoke a static method on the type wrapped by this Reflector instance
      Type Parameters:
      R - the return type
      Parameters:
      methodName - the name of the method that will be invoked
      arguments - the arguments that will be passed to the matching static method.
      The arguments will be converted to Parameters.argumentTypes(Object...) and the search for a matching static method uses the Parameters.parameterTypesMatches(Class[], Class[], boolean) without requiring an exact parameter type match
      Returns:
      the result of invoking the static method
      Throws:
      NoMatchingMethodFoundException - if a matching method cannot be found
      MethodInvocationFailedException - if the method invocation fails
      See Also:
    • invokeStatic

      public <R> R invokeStatic(Method method, Object... arguments)
      Invoke the static on the type wrapped by this Reflector instance
      Type Parameters:
      R - the return type
      Parameters:
      method - the method that will be invoked
      arguments - the arguments that will be passed to the static method.
      Returns:
      the result of invoking the static method
      Throws:
      MethodInvocationFailedException - if the method invocation fails
      See Also:
    • invoke

      public <R> R invoke(String methodName, Object invokeOnObject, Object... withArguments)
      Invoke an instance method on the invokeOnObject instance
      Type Parameters:
      R - the return type
      Parameters:
      methodName - the name of the method that will be invoked
      invokeOnObject - the object instance that the matching method will be invoked on
      withArguments - the arguments that will be passed to the matching instance method.
      The arguments will be converted to Parameters.argumentTypes(Object...) and the search for a matching method on the type wrapped by this Reflector instance. The parameter matching uses the Parameters.parameterTypesMatches(Class[], Class[], boolean) without requiring an exact parameter type match
      Returns:
      the result of invoking the method
      Throws:
      NoMatchingMethodFoundException - if a matching method cannot be found
      MethodInvocationFailedException - if the method invocation fails
      See Also:
    • invoke

      public <R> R invoke(Method method, Object invokeOnObject, Object... withArguments)
      Invoke the instance method on the invokeOnObject instance
      Type Parameters:
      R - the return type
      Parameters:
      method - the method that will be invoked
      invokeOnObject - the object instance that the matching method will be invoked on
      withArguments - the arguments that will be passed to the instance method.<
      Returns:
      the result of invoking the method
      Throws:
      NoMatchingMethodFoundException - if a matching method cannot be found
      MethodInvocationFailedException - if the method invocation fails
    • findFieldByName

      public Optional<Field> findFieldByName(String fieldName)
      Find the instance Field, in the type wrapped by this Reflector instance, that matches on the field name
      Parameters:
      fieldName - the name of the field we're searching for
      Returns:
      an Optional with the matching Field, otherwise an Optional.empty() if no matching field can be found
    • findStaticFieldByName

      public Optional<Field> findStaticFieldByName(String fieldName)
      Find the static Field, in the type wrapped by this Reflector instance, that matches on the field name
      Parameters:
      fieldName - the name of the field we're searching for
      Returns:
      an Optional with the matching Field, otherwise an Optional.empty() if no matching field can be found
    • get

      public <R> R get(Object object, String fieldName)
      Get the value of an instance field
      Type Parameters:
      R - the return type
      Parameters:
      object - the object where the field value will get read from
      fieldName - the name of the field
      Returns:
      the value of the field
      Throws:
      NoFieldFoundException - in case we couldn't find a field with a matching name in the type wrapped by this Reflector instance
      GetFieldException - in case getting the field value fails
    • get

      public <R> R get(Object object, Field field)
      Get the value of an instance field
      Type Parameters:
      R - the return type
      Parameters:
      object - the object where the field value will get read from
      field - the field to read
      Returns:
      the value of the field
      Throws:
      NoFieldFoundException - in case we couldn't find a field with a matching name
      GetFieldException - in case getting the field value fails
    • getStatic

      public <R> R getStatic(String fieldName)
      Get the value of a static field on the type wrapped by this Reflector instance
      Type Parameters:
      R - the return type
      Parameters:
      fieldName - the name of the field
      Returns:
      the value of the field
      Throws:
      NoFieldFoundException - in case we couldn't find a field with a matching name in the type wrapped by this Reflector instance
      GetFieldException - in case getting the field value fails
    • getStatic

      public <R> R getStatic(Field field)
      Get the value of a static field on the type wrapped by this Reflector instance
      Type Parameters:
      R - the return type
      Parameters:
      field - the static field to read
      Returns:
      the value of the field
      Throws:
      GetFieldException - in case getting the field value fails
    • set

      public void set(Object object, String fieldName, Object newFieldValue)
      Set the instance field to the provided newFieldValue
      Parameters:
      object - the object where the field value will get read from
      fieldName - the name of the field
      newFieldValue - the new value of the field
      Throws:
      NoFieldFoundException - in case we couldn't find a field with a matching name in the type wrapped by this Reflector instance
      SetFieldException - in case setting the field value fails
    • set

      public void set(Object object, Field field, Object newFieldValue)
      Set the instance field to the provided newFieldValue
      Parameters:
      object - the object where the field value will get read from
      field - the field on which to set a new value
      newFieldValue - the new value of the field
      Throws:
      NoFieldFoundException - in case we couldn't find a field with a matching name in the type wrapped by this Reflector instance
      SetFieldException - in case setting the field value fails
    • setStatic

      public void setStatic(String fieldName, Object newFieldValue)
      Set the static field, on the type wrapped by this Reflector instance, to the provided newFieldValue
      Parameters:
      fieldName - the name of the field
      newFieldValue - the new value of the field
      Throws:
      NoFieldFoundException - in case we couldn't find a field with a matching name in the type wrapped by this Reflector instance
      SetFieldException - in case setting the field value fails
    • setStatic

      public void setStatic(Field field, Object newFieldValue)
      Set the static field, on the type wrapped by this Reflector instance, to the provided newFieldValue
      Parameters:
      field - the field on which to set a new value
      newFieldValue - the new value of the field
      Throws:
      SetFieldException - in case setting the field value fails
    • findFieldByAnnotation

      public Optional<Field> findFieldByAnnotation(Class<? extends Annotation> annotation)
      Find the Field in the type wrapped by this Reflector instance, which has the specified annotation
      Parameters:
      annotation - the annotation
      Returns:
      an Optional with the matching Field, otherwise an Optional.empty() if no matching field can be found
      Throws:
      TooManyMatchingFieldsFoundException - in case we found more than one field with the specified annotation
    • staticFields

      public Stream<Field> staticFields()
      Return a Stream of static Field's
      Returns:
      Return a Stream of static Field's
    • instanceFields

      public Stream<Field> instanceFields()
      Return a Stream of instance (non-static) Field's
      Returns:
      Return a Stream of instance (non-static) Field's