bb.util
Class ReflectUtil

java.lang.Object
  extended by bb.util.ReflectUtil

public final class ReflectUtil
extends Object

Provides static utility methods related to reflection.

This class is multithread safe: it is stateless.

Author:
Brent Boyer

Nested Class Summary
static class ReflectUtil.FieldComparator
          Imposes an ordering on Fields that is consistent with equals; see compare for details.
static class ReflectUtil.UnitTest
          See the Overview page of the project's javadocs for a general description of this unit test class.
 
Field Summary
private static Object[] noArgParameters
          An empty Object[] that caches the parameter used by callLogError(Object, String).
private static Class[] noArgSignature
          An empty Class[] that caches the signature used by callLogError(Object, String).
 
Constructor Summary
private ReflectUtil()
          This private constructor suppresses the default (public) constructor, ensuring non-instantiability.
 
Method Summary
static Object callLogError(Object obj, String methodName)
          Returns callLogError(Object, String, Class[], Object[])(obj, methodName, noArgSignature, noArgParameters).
static Object callLogError(Object obj, String methodName, Class[] paramClasses, Object[] paramValues)
          Uses getMethod to find a method named methodName with a signature given by paramClasses on obj, and then invokes that method on obj using paramValues and returns the result.
static String diagnoseGetProblem(Throwable t)
          Returns a useful diagnostic message for a Throwable generated when calling Field.get.
static String fieldsDeclaredReport(Object obj)
          Returns a String describing all of obj's declared fields (i.e. just those fields declared in the obj's class itself, whether static or instance, regardless of access level, but never including fields from superclasses/superinterfaces).
static Class[] findSignature(Object[] arguments)
          Returns a Class[] where each element is the Class of the corresponding Object in the arguments array.
static Object get(Object obj, String fieldName)
          Accesses the value of the field of obj which is named fieldName.
static
<E extends Enum<E>>
E[]
getEnumValues(E e)
          Uses reflection to find and execute a static method named "values" that takes no arguments.
static Method getMethod(Object obj, String methodName, Class[] paramClasses)
          Uses reflection to find a method named methodName with a signature given by paramClasses on obj.
static boolean isDefault(Field f)
          Returns true if f has default (unnamed) access.
static boolean isFinal(Field f)
          Returns Modifier.isFinal( f.
static boolean isPrivate(Field f)
          Returns Modifier.isPrivate( f.
static boolean isProtected(Field f)
          Returns Modifier.isProtected( f.
static boolean isPublic(Field f)
          Returns Modifier.isPublic( f.
static boolean isStatic(Field f)
          Returns Modifier.isStatic( f.
static void set(Object obj, String fieldName, Object value)
          Mutates the value of the field of obj which is named fieldName.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

noArgSignature

private static final Class[] noArgSignature
An empty Class[] that caches the signature used by callLogError(Object, String).


noArgParameters

private static final Object[] noArgParameters
An empty Object[] that caches the parameter used by callLogError(Object, String).

Constructor Detail

ReflectUtil

private ReflectUtil()
This private constructor suppresses the default (public) constructor, ensuring non-instantiability.

Method Detail

getEnumValues

public static <E extends Enum<E>> E[] getEnumValues(E e)
                                         throws RuntimeException
Uses reflection to find and execute a static method named "values" that takes no arguments. Such a method is guaranteed to be injected into every Java enum by the compiler.

You can always easily get all the values of an enum if you know the specific class name at compile time. For example, if you have an enum named Planet, then your can call Planet.values(). The purpose of this method, however, is to get all the values of an enum when you do not know its specific classname, but are working with a type parameter that merely says that it is an enum.

Throws:
RuntimeException - should actually be one of:
  1. IllegalArgumentException if e is null
  2. SecurityException see Class.getMethod
(this method declares that it throws RuntimeException not only for simplicity, but also because otherwise would be forced by the compiler to declare a bunch of other checked exception types that should never be thrown here)

get

public static Object get(Object obj,
                         String fieldName)
                  throws Exception
Accesses the value of the field of obj which is named fieldName.

The implementation here suppresses all Java access checks, which means that it can be used to return the values of, say, private fields. Warning: this check suppression fails with certain classes (e.g. security sensitive ones from the JDK).

Throws:
Exception - should actually be one of:
  1. IllegalArgumentException if obj is null; fieldName is blank
  2. NoSuchFieldException if a field with fieldName is not found
  3. NullPointerException if fieldName is null
  4. SecurityException see Class.getDeclaredField; Field.setAccessible
(this method declares that it throws Exception not only for simplicity, but also because otherwise would be forced by the compiler to declare a bunch of other checked exception types that should never be thrown here)

set

public static void set(Object obj,
                       String fieldName,
                       Object value)
                throws Exception
Mutates the value of the field of obj which is named fieldName.

The implementation here suppresses all Java access checks, which means that it can be used to set the values of, say, private and/or final fields. Warning: this check suppression fails with certain classes (e.g. security sensitive ones from the JDK).

Throws:
Exception - should actually be one of:
  1. IllegalArgumentException if obj is null; fieldName is blank
  2. NoSuchFieldException if a field with fieldName is not found
  3. SecurityException see Class.getDeclaredField; Field.setAccessible
(this method declares that it throws Exception not only for simplicity, but also because otherwise would be forced by the compiler to declare a bunch of other checked exception types that should never be thrown here)

diagnoseGetProblem

public static String diagnoseGetProblem(Throwable t)
                                 throws IllegalArgumentException
Returns a useful diagnostic message for a Throwable generated when calling Field.get.

Throws:
IllegalArgumentException - if t is null

fieldsDeclaredReport

public static String fieldsDeclaredReport(Object obj)
                                   throws RuntimeException
Returns a String describing all of obj's declared fields (i.e. just those fields declared in the obj's class itself, whether static or instance, regardless of access level, but never including fields from superclasses/superinterfaces). Each field's description starts with the result of calling Field.toString() and ends with its value in obj. The fields are ordered by ReflectUtil.FieldComparator instance.

Throws:
RuntimeException - should actually be one of:
  1. IllegalArgumentException if obj is null
  2. SecurityException see Class.getDeclaredField; Field.setAccessible
This method ensures that it only throws RuntimeException by catching all Throwables and wrapping them in a RuntimeException if not already one before rethrowing them. This is done not only for the convenience of the caller, but also because otherwise would be forced by the compiler to declare a bunch of checked exceptions that should never be thrown here.

getMethod

public static Method getMethod(Object obj,
                               String methodName,
                               Class[] paramClasses)
                        throws Exception
Uses reflection to find a method named methodName with a signature given by paramClasses on obj. First searches for a matching public method that is declared in obj's Class, or else one of its ancestors. As a fallback if that search fails, searches for any (non-public) matching method that is declared only in obj's Class.

Contract: the result is never null, and is always marked as accessible by a call to setAccessible(true).

Throws:
Exception - should actually be one of:
  1. IllegalArgumentException if obj is null; methodName is blank
  2. SecurityException see Class.getMethod; Class.getDeclaredMethod
  3. NoSuchMethodException if a matching method is not found

callLogError

public static Object callLogError(Object obj,
                                  String methodName)
Returns callLogError(Object, String, Class[], Object[])(obj, methodName, noArgSignature, noArgParameters). This is a convenience method for calling no-arg methods.


callLogError

public static Object callLogError(Object obj,
                                  String methodName,
                                  Class[] paramClasses,
                                  Object[] paramValues)
Uses getMethod to find a method named methodName with a signature given by paramClasses on obj, and then invokes that method on obj using paramValues and returns the result.

Contract: this method should never throw a Throwable. Any Throwable that is raised is caught and logged robustly to the default Logger. An example of such a Throwable is a NoSuchMethodException if obj does not actually have the specified method. If such a Throwable is caught, the result of this method is null. Warning: null could also be the normal result of the method invocation, so it is imposible to use that to determine if a problem happened.

Motivation: this method was originally written to support resource closing methods of objects inside finally blocks (e.g. this method is used by StreamUtil.close(Object)). The issue here is that the finally block may need multiple such methods to be called, so none should not throw a Throwable because that would stop subsequent resources from being closed. Using this method allows each to be conveniently called with its own error handling, as opposed to wrapping each method inside its own dedicated try-catch block.


isPublic

public static boolean isPublic(Field f)
Returns Modifier.isPublic( f.Field.getModifiers() ).


isProtected

public static boolean isProtected(Field f)
Returns Modifier.isProtected( f.Field.getModifiers() ).


isDefault

public static boolean isDefault(Field f)
Returns true if f has default (unnamed) access. This is determined by the logic !isPublic(f) && !isProtected(f) && >!isPrivate(f).


isPrivate

public static boolean isPrivate(Field f)
Returns Modifier.isPrivate( f.Field.getModifiers() ).


isStatic

public static boolean isStatic(Field f)
Returns Modifier.isStatic( f.Field.getModifiers() ).


isFinal

public static boolean isFinal(Field f)
Returns Modifier.isFinal( f.Field.getModifiers() ).


findSignature

public static Class[] findSignature(Object[] arguments)
Returns a Class[] where each element is the Class of the corresponding Object in the arguments array. If arguments is null, a zero-element array is returned.