blob: d3617b9795e0a90cc0b1c98fc694e7927bbdc639 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2012 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.common.utility.internal;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
/**
* Convenience methods related to the <code>java.lang.reflect</code> package.
* These methods provide shortcuts for manipulating objects via
* reflection; particularly when dealing with fields and/or methods that
* are not publicly accessible or are inherited.
* <p>
* In most cases, all exceptions are handled and wrapped in
* {@link java.lang.RuntimeException}s; so these methods should
* be used when there should be no problems using reflection (i.e.
* the referenced members are presumably present etc.).
* <p>
* There are also a number of methods whose names
* end with an underscore. These methods declare the expected checked
* exceptions (e.g. {@link NoSuchMethodException}, {@link NoSuchFieldException}).
* These methods can be used to probe
* for methods, fields, etc. that should be present but might not be.
*/
public final class ReflectionTools {
public static final Class<?>[] ZERO_PARAMETER_TYPES = new Class[0];
public static final Object[] ZERO_ARGUMENTS = new Object[0];
private static final String CR = StringTools.CR;
public static final Class<?> VOID_CLASS = void.class;
public static final Class<java.lang.Void> VOID_WRAPPER_CLASS = java.lang.Void.class;
// ********** fields **********
/**
* Get a field value, given the containing object and field name.
* Return its result.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Object.getFieldValue(String fieldName)</code>
*/
public static Object getFieldValue(Object object, String fieldName) {
try {
return getFieldValue_(object, fieldName);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(object, fieldName), ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(object, fieldName), ex);
}
}
/**
* Get a field value, given the containing object and field name.
* Return its result.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Object.getFieldValue(String fieldName)</code>
*/
public static Object getFieldValue_(Object object, String fieldName)
throws NoSuchFieldException, IllegalAccessException
{
return getField_(object, fieldName).get(object);
}
/**
* Get a static field value, given the containing class and field name.
* Return its result.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Class.getStaticFieldValue(String fieldName)</code>
*/
public static Object getStaticFieldValue(Class<?> javaClass, String fieldName) {
try {
return getStaticFieldValue_(javaClass, fieldName);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(javaClass, fieldName), ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(javaClass, fieldName), ex);
}
}
/**
* Get a static field value, given the containing class and field name.
* Return its result.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Class.getStaticFieldValue(String fieldName)</code>
*/
public static Object getStaticFieldValue_(Class<?> javaClass, String fieldName)
throws NoSuchFieldException, IllegalAccessException
{
return getField_(javaClass, fieldName).get(null);
}
/**
* Set a field value, given the containing object, field name, and new value.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Object.setFieldValue(String fieldName, Object value)</code>
*/
public static void setFieldValue(Object object, String fieldName, Object value) {
try {
setFieldValue_(object, fieldName, value);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(object, fieldName), ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(object, fieldName), ex);
}
}
/**
* Set a field value, given the containing object, field name, and new value.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Object.setFieldValue(String fieldName, Object value)</code>
*/
public static void setFieldValue_(Object object, String fieldName, Object value)
throws NoSuchFieldException, IllegalAccessException
{
getField_(object, fieldName).set(object, value);
}
/**
* Set a static field value, given the containing class, field name, and new value.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Class.setStaticFieldValue(String fieldName, Object value)</code>
*/
public static void setStaticFieldValue(Class<?> javaClass, String fieldName, Object value) {
try {
setStaticFieldValue_(javaClass, fieldName, value);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(javaClass, fieldName), ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(javaClass, fieldName), ex);
}
}
/**
* Set a static field value, given the containing class, field name, and new value.
* Useful for accessing private, package, or protected fields.
* <p>
* <code>Class.setStaticFieldValue(String fieldName, Object value)</code>
*/
public static void setStaticFieldValue_(Class<?> javaClass, String fieldName, Object value)
throws NoSuchFieldException, IllegalAccessException
{
getField_(javaClass, fieldName).set(null, value);
}
/**
* Convenience method.
* Return a field for the specified object and field name.
* If the object's class does not directly
* define the field, look for it in the class's superclasses.
* Make any private/package/protected field accessible.
* <p>
* <code>Object.getField(String fieldName)</code>
*/
public static Field getField(Object object, String fieldName) {
try {
return getField_(object, fieldName);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(object, fieldName), ex);
}
}
/**
* Convenience method.
* Return a field for the specified object and field name.
* If the object's class does not directly
* define the field, look for it in the class's superclasses.
* Make any private/package/protected field accessible.
* <p>
* <code>Object.getField(String fieldName)</code>
*/
public static Field getField_(Object object, String fieldName)
throws NoSuchFieldException
{
return getField_(object.getClass(), fieldName);
}
/**
* Return a field for the specified class and field name.
* If the class does not directly
* define the field, look for it in the class's superclasses.
* Make any private/package/protected field accessible.
*/
public static Field getField(Class<?> javaClass, String fieldName) {
try {
return getField_(javaClass, fieldName);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedFieldName(javaClass, fieldName), ex);
}
}
/**
* Return a field for the specified class and field name.
* If the class does not directly
* define the field, look for it in the class's superclasses.
* Make any private/package/protected field accessible.
*/
public static Field getField_(Class<?> javaClass, String fieldName)
throws NoSuchFieldException
{
Field field = null;
try {
field = javaClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException ex) {
Class<?> superclass = javaClass.getSuperclass();
if (superclass == null) {
throw ex;
}
return getField_(superclass, fieldName); // recurse
}
field.setAccessible(true);
return field;
}
/**
* Return all the fields for the
* specified class, including inherited fields.
* Make any private/package/protected fields accessible.
* <p>
* <code>Class.getAllFields()</code>
*/
public static Iterable<Field> getAllFields(Class<?> javaClass) {
ArrayList<Field> fields = new ArrayList<Field>();
for (Class<?> tempClass = javaClass; tempClass != null; tempClass = tempClass.getSuperclass()) {
addDeclaredFieldsTo(tempClass, fields);
}
return fields;
}
/*
* Add the declared fields for the specified class
* to the specified list.
*/
private static void addDeclaredFieldsTo(Class<?> javaClass, ArrayList<Field> fields) {
for (Field field : getDeclaredFields(javaClass)) {
fields.add(field);
}
}
/**
* Return the declared fields for the specified class.
* Make any private/package/protected fields accessible.
* <p>
* <code>Class.getAccessibleDeclaredFields()</code>
*/
public static Iterable<Field> getDeclaredFields(Class<?> javaClass) {
Field[] fields = javaClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
}
return new ArrayIterable<Field>(fields);
}
// ********** methods **********
/**
* Convenience method.
* Execute a zero-argument method, given the receiver and method name.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Object.execute(String methodName)</code>
*/
public static Object executeMethod(Object receiver, String methodName) {
return executeMethod(receiver, methodName, ZERO_PARAMETER_TYPES, ZERO_ARGUMENTS);
}
/**
* Convenience method.
* Execute a one-argument method, given the receiver,
* method name, parameter type, and argument.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Object.execute(String methodName, Class<?> parameterType, Object argument)</code>
*/
public static Object executeMethod(Object receiver, String methodName, Class<?> parameterType, Object argument) {
return executeMethod(receiver, methodName, new Class[] {parameterType}, new Object[] {argument});
}
/**
* Execute a method, given the receiver,
* method name, parameter types, and arguments.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Object.execute(String methodName, Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static Object executeMethod(Object receiver, String methodName, Class<?>[] parameterTypes, Object[] arguments) {
return executeMethod(getMethod(receiver, methodName, parameterTypes), receiver, arguments);
}
/**
* Execute the specified method, given the receiver and arguments.
* Return its result.
* Useful for invoking cached methods.
*/
public static Object executeMethod(Method method, Object receiver, Object[] arguments) {
try {
return method.invoke(receiver, arguments);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + method, ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException(method + CR + ex.getTargetException(), ex);
}
}
/**
* Convenience method.
* Execute a zero-argument method,
* given the receiver and method name.
* Return its result.
* Throw an exception if the method is not defined.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Object.execute(String methodName)</code>
*/
public static Object executeMethod_(Object receiver, String methodName)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
return executeMethod_(receiver, methodName, ZERO_PARAMETER_TYPES, ZERO_ARGUMENTS);
}
/**
* Convenience method.
* Execute a method, given the receiver,
* method name, parameter type, and argument.
* Return its result.
* Throw an exception if the method is not defined.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Object.execute(String methodName, Class<?> parameterType, Object argument)</code>
*/
public static Object executeMethod_(Object receiver, String methodName, Class<?> parameterType, Object argument)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
return executeMethod_(receiver, methodName, new Class[] {parameterType}, new Object[] {argument});
}
/**
* Execute a method, given the receiver,
* method name, parameter types, and arguments.
* Return its result.
* Throw an exception if the method is not defined.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Object.execute(String methodName, Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static Object executeMethod_(Object receiver, String methodName, Class<?>[] parameterTypes, Object[] arguments)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
return getMethod_(receiver, methodName, parameterTypes).invoke(receiver, arguments);
}
/**
* Convenience method.
* Execute a zero-argument static method,
* given the class and method name.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Class.executeStaticMethod(String methodName)</code>
*/
public static Object executeStaticMethod(Class<?> javaClass, String methodName) {
return executeStaticMethod(javaClass, methodName, ZERO_PARAMETER_TYPES, ZERO_ARGUMENTS);
}
/**
* Convenience method.
* Execute a static method, given the class,
* method name, parameter type, and argument.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Class.executeStaticMethod(String methodName, Class<?> parameterType, Object argument)</code>
*/
public static Object executeStaticMethod(Class<?> javaClass, String methodName, Class<?> parameterType, Object argument) {
return executeStaticMethod(javaClass, methodName, new Class[] {parameterType}, new Object[] {argument});
}
/**
* Execute a static method, given the class,
* method name, parameter types, and arguments.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Class.executeStaticMethod(String methodName, Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static Object executeStaticMethod(Class<?> javaClass, String methodName, Class<?>[] parameterTypes, Object[] arguments) {
try {
return executeStaticMethod_(javaClass, methodName, parameterTypes, arguments);
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedMethodSignature(javaClass, methodName, parameterTypes), ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedMethodSignature(javaClass, methodName, parameterTypes), ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException(buildFullyQualifiedMethodSignature(javaClass, methodName, parameterTypes) + CR + ex.getTargetException(), ex);
}
}
/**
* Convenience method.
* Execute a zero-argument static method,
* given the class and method name.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Class.executeStaticMethod(String methodName)</code>
*/
public static Object executeStaticMethod_(Class<?> javaClass, String methodName)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
return executeStaticMethod_(javaClass, methodName, ZERO_PARAMETER_TYPES, ZERO_ARGUMENTS);
}
/**
* Convenience method.
* Execute a static method, given the class,
* method name, parameter type, and argument.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Class.executeStaticMethod(String methodName, Class<?> parameterType, Object argument)</code>
*/
public static Object executeStaticMethod_(Class<?> javaClass, String methodName, Class<?> parameterType, Object argument)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
return executeStaticMethod_(javaClass, methodName, new Class[] {parameterType}, new Object[] {argument});
}
/**
* Execute a static method, given the class,
* method name, parameter types, and arguments.
* Return its result.
* Useful for invoking private, package, or protected methods.
* <p>
* <code>Class.executeStaticMethod(String methodName, Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static Object executeStaticMethod_(Class<?> javaClass, String methodName, Class<?>[] parameterTypes, Object[] arguments)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
return getStaticMethod_(javaClass, methodName, parameterTypes).invoke(null, arguments);
}
/**
* Convenience method.
* Return a zero-argument method for the specified class
* and method name. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod(Class<?> javaClass, String methodName) {
return getMethod(javaClass, methodName, ZERO_PARAMETER_TYPES);
}
/**
* Convenience method.
* Return a zero-argument method for the specified class
* and method name. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod_(Class<?> javaClass, String methodName)
throws NoSuchMethodException
{
return getMethod_(javaClass, methodName, ZERO_PARAMETER_TYPES);
}
/**
* Convenience method.
* Return a method for the specified class, method name,
* and formal parameter type. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod(Class<?> javaClass, String methodName, Class<?> parameterType) {
return getMethod(javaClass, methodName, new Class[] {parameterType});
}
/**
* Convenience method.
* Return a method for the specified class, method name,
* and formal parameter type. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod_(Class<?> javaClass, String methodName, Class<?> parameterType)
throws NoSuchMethodException
{
return getMethod_(javaClass, methodName, new Class[] {parameterType});
}
/**
* Return a method for the specified class, method name,
* and formal parameter types. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod(Class<?> javaClass, String methodName, Class<?>[] parameterTypes) {
try {
return getMethod_(javaClass, methodName, parameterTypes);
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedMethodSignature(javaClass, methodName, parameterTypes), ex);
}
}
/**
* Return a method for the specified class, method name,
* and formal parameter types. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod_(Class<?> javaClass, String methodName, Class<?>[] parameterTypes)
throws NoSuchMethodException
{
Method method = null;
try {
method = javaClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException ex) {
Class<?> superclass = javaClass.getSuperclass();
if (superclass == null) {
throw ex;
}
// recurse
return getMethod_(superclass, methodName, parameterTypes);
}
method.setAccessible(true);
return method;
}
/**
* Convenience method.
* Return a zero-argument method for the specified object
* and method name. If the object's class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod(Object object, String methodName) {
return getMethod(object.getClass(), methodName);
}
/**
* Convenience method.
* Return a zero-argument method for the specified object
* and method name. If the object's class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod_(Object object, String methodName)
throws NoSuchMethodException
{
return getMethod_(object.getClass(), methodName);
}
/**
* Convenience method.
* Return a method for the specified object, method name,
* and formal parameter types. If the object's class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod(Object object, String methodName, Class<?>[] parameterTypes) {
return getMethod(object.getClass(), methodName, parameterTypes);
}
/**
* Convenience method.
* Return a method for the specified object, method name,
* and formal parameter types. If the object's class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod_(Object object, String methodName, Class<?>[] parameterTypes)
throws NoSuchMethodException
{
return getMethod_(object.getClass(), methodName, parameterTypes);
}
/**
* Convenience method.
* Return a method for the specified object, method name,
* and formal parameter type. If the object's class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod(Object object, String methodName, Class<?> parameterType) {
return getMethod(object.getClass(), methodName, parameterType);
}
/**
* Convenience method.
* Return a method for the specified object, method name,
* and formal parameter type. If the object's class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getMethod_(Object object, String methodName, Class<?> parameterType)
throws NoSuchMethodException
{
return getMethod_(object.getClass(), methodName, parameterType);
}
/**
* Convenience method.
* Return a zero-argument static method for the specified class
* and method name. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getStaticMethod(Class<?> javaClass, String methodName) {
return getStaticMethod(javaClass, methodName, ZERO_PARAMETER_TYPES);
}
/**
* Convenience method.
* Return a static method for the specified class, method name,
* and formal parameter type. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getStaticMethod(Class<?> javaClass, String methodName, Class<?> parameterTypes) {
return getStaticMethod(javaClass, methodName, new Class[] {parameterTypes});
}
/**
* Return a static method for the specified class, method name,
* and formal parameter types. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getStaticMethod(Class<?> javaClass, String methodName, Class<?>[] parameterTypes) {
try {
return getStaticMethod_(javaClass, methodName, parameterTypes);
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedMethodSignature(javaClass, methodName, parameterTypes), ex);
}
}
/**
* Convenience method.
* Return a zero-argument static method for the specified class
* and method name. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getStaticMethod_(Class<?> javaClass, String methodName)
throws NoSuchMethodException
{
return getStaticMethod_(javaClass, methodName, ZERO_PARAMETER_TYPES);
}
/**
* Convenience method.
* Return a static method for the specified class, method name,
* and formal parameter type. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getStaticMethod_(Class<?> javaClass, String methodName, Class<?> parameterTypes)
throws NoSuchMethodException
{
return getStaticMethod_(javaClass, methodName, new Class[] {parameterTypes});
}
/**
* Return a static method for the specified class, method name,
* and formal parameter types. If the class does not directly
* implement the method, look for it in the class's superclasses.
* Make any private/package/protected method accessible.
*/
public static Method getStaticMethod_(Class<?> javaClass, String methodName, Class<?>[] parameterTypes)
throws NoSuchMethodException
{
Method method = getMethod_(javaClass, methodName, parameterTypes);
if (Modifier.isStatic(method.getModifiers())) {
return method;
}
throw new NoSuchMethodException(buildFullyQualifiedMethodSignature(javaClass, methodName, parameterTypes));
}
/**
* Return all the methods for the
* specified class, including inherited methods.
* Make any private/package/protected methods accessible.
* <p>
* <code>Class.getAllMethods()</code>
*/
public static Iterable<Method> getAllMethods(Class<?> javaClass) {
ArrayList<Method> methods = new ArrayList<Method>();
for (Class<?> tempClass = javaClass; tempClass != null; tempClass = tempClass.getSuperclass()) {
addDeclaredMethodsTo(tempClass, methods);
}
return methods;
}
/*
* Add the declared methods for the specified class
* to the specified list.
*/
private static void addDeclaredMethodsTo(Class<?> javaClass, ArrayList<Method> methods) {
for (Method method : getDeclaredMethods(javaClass)) {
methods.add(method);
}
}
/**
* Return the declared methods for the specified class.
* Make any private/package/protected methods accessible.
* <p>
* <code>Class.getAccessibleDeclaredMethods()</code>
*/
public static Iterable<Method> getDeclaredMethods(Class<?> javaClass) {
Method[] methods = javaClass.getDeclaredMethods();
for (Method method : methods) {
method.setAccessible(true);
}
return new ArrayIterable<Method>(methods);
}
// ********** constructors **********
/**
* Return the default (zero-argument) constructor
* for the specified class.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getDefaultConstructor()</code>
*/
public static <T> Constructor<T> getDefaultConstructor(Class<T> javaClass) {
return getConstructor(javaClass);
}
/**
* Convenience method.
* Return the default (zero-argument) constructor
* for the specified class.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getConstructor()</code>
*/
public static <T> Constructor<T> getConstructor(Class<T> javaClass) {
return getConstructor(javaClass, ZERO_PARAMETER_TYPES);
}
/**
* Convenience method.
* Return the constructor for the specified class
* and formal parameter type.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getConstructor(Class<?> parameterType)</code>
*/
public static <T> Constructor<T> getConstructor(Class<T> javaClass, Class<?> parameterType) {
return getConstructor(javaClass, new Class[] {parameterType});
}
/**
* Return the constructor for the specified class
* and formal parameter types.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getConstructor(Class<?>[] parameterTypes)</code>
*/
public static <T> Constructor<T> getConstructor(Class<T> javaClass, Class<?>[] parameterTypes) {
try {
return getConstructor_(javaClass, parameterTypes);
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedConstructorSignature(javaClass, parameterTypes), ex);
}
}
/**
* Return the default (zero-argument) constructor
* for the specified class.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getDefaultConstructor()</code>
*/
public static <T> Constructor<T> getDefaultConstructor_(Class<T> javaClass)
throws NoSuchMethodException
{
return getConstructor_(javaClass);
}
/**
* Convenience method.
* Return the default (zero-argument) constructor
* for the specified class.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getConstructor()</code>
*/
public static <T> Constructor<T> getConstructor_(Class<T> javaClass)
throws NoSuchMethodException
{
return getConstructor_(javaClass, ZERO_PARAMETER_TYPES);
}
/**
* Convenience method.
* Return the constructor for the specified class
* and formal parameter type.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getConstructor(Class<?> parameterType)</code>
*/
public static <T> Constructor<T> getConstructor_(Class<T> javaClass, Class<?> parameterType)
throws NoSuchMethodException
{
return getConstructor_(javaClass, new Class[] {parameterType});
}
/**
* Return the constructor for the specified class
* and formal parameter types.
* Make any private/package/protected constructor accessible.
* <p>
* <code>Class.getConstructor(Class<?>[] parameterTypes)</code>
*/
public static <T> Constructor<T> getConstructor_(Class<T> javaClass, Class<?>[] parameterTypes)
throws NoSuchMethodException
{
Constructor<T> constructor = javaClass.getDeclaredConstructor(parameterTypes);
constructor.setAccessible(true);
return constructor;
}
/**
* Return the declared constructors for the specified class.
* Make any private/package/protected constructors accessible.
* <p>
* <code>Class.getAccessibleDeclaredConstructors()</code>
*/
public static <T> Iterable<Constructor<T>> getDeclaredConstructors(Class<T> javaClass) {
@SuppressWarnings("unchecked")
Constructor<T>[] constructors = javaClass.getDeclaredConstructors();
for (Constructor<T> constructor : constructors) {
constructor.setAccessible(true);
}
return new ArrayIterable<Constructor<T>>(constructors);
}
// ********** classes **********
/**
* Convenience method.
* Return the specified class (without the checked exception).
*/
public static Class<?> classForName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(className, ex);
}
}
/**
* Convenience method.
* Return the specified class (without the checked exception).
*/
public static Class<?> classForName(String className, boolean initialize, ClassLoader classLoader) {
try {
return Class.forName(className, initialize, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(className, ex);
}
}
/**
* Return the "array depth" of the specified class.
* The depth is the number of dimensions for an array type.
* Non-array types have a depth of zero.
* <p>
* <code>Class.getArrayDepth()</code>
*/
public static int getArrayDepth(Class<?> javaClass) {
int depth = 0;
while (javaClass.isArray()) {
depth++;
javaClass = javaClass.getComponentType();
}
return depth;
}
/**
* Return the "element type" of the specified class.
* The element type is the base type held by an array type.
* A non-array type simply returns itself.
* <p>
* <code>Class.getElementType()</code>
*/
public static Class<?> getElementType(Class<?> javaClass) {
while (javaClass.isArray()) {
javaClass = javaClass.getComponentType();
}
return javaClass;
}
/**
* Return the wrapper class corresponding to the specified
* primitive class. Return <code>null</code> if the specified class
* is not a primitive class.
* <p>
* <code>Class.getWrapperClass()</code>
*/
public static Class<?> getWrapperClass(Class<?> primitiveClass) {
for (Primitive primitive : PRIMITIVES) {
if (primitive.javaClass == primitiveClass) {
return primitive.wrapperClass;
}
}
return null;
}
/**
* Return whether the specified class is a primitive wrapper
* class (i.e. <code>java.lang.Void</code> or one of the primitive
* variable wrapper classes, <code>java.lang.Boolean</code>,
* <code>java.lang.Integer</code>, <code>java.lang.Float</code>, etc.).
* <p>
* <strong>NB:</strong> <code>void.class.isPrimitive() == true</code>
* <p>
* <code>Class.isPrimitiveWrapper()</code>
*/
public static boolean classIsPrimitiveWrapper(Class<?> javaClass) {
if (javaClass.isArray() || (javaClass.getName().length() > MAX_PRIMITIVE_WRAPPER_CLASS_NAME_LENGTH)) {
return false; // performance tweak
}
for (Primitive primitive : PRIMITIVES) {
if (javaClass == primitive.wrapperClass) {
return true;
}
}
return false;
}
/**
* Return whether the specified class is a "variable" primitive wrapper
* class (i.e. <code>java.lang.Boolean</code>,
* <code>java.lang.Integer</code>, <code>java.lang.Float</code>, etc.,
* but not <code>java.lang.Void</code>).
* <p>
* <strong>NB:</strong> <code>void.class.isPrimitive() == true</code>
* <p>
* <code>Class.isVariablePrimitiveWrapper()</code>
*/
public static boolean classIsVariablePrimitiveWrapper(Class<?> javaClass) {
return classIsPrimitiveWrapper(javaClass)
&& (javaClass != VOID_WRAPPER_CLASS);
}
/**
* Return whether the specified class is a "variable" primitive
* class (i.e. <code>boolean</code>, <code>int</code>,
* <code>float</code>, etc., but not <code>void</code>).
* <p>
* <strong>NB:</strong> <code>void.class.isPrimitive() == true</code>
* <p>
* <code>Class.isVariablePrimitive()</code>
*/
public static boolean classIsVariablePrimitive(Class<?> javaClass) {
return javaClass.isPrimitive() && (javaClass != VOID_CLASS);
}
/**
* Return the primitive class for the specified primitive class code.
* Return <code>null</code> if the specified code
* is not a primitive class code.
* @see java.lang.Class#getName()
*/
public static Class<?> getClassForCode(int classCode) {
return getClassForCode((char) classCode);
}
/**
* Return the primitive class for the specified primitive class code.
* Return <code>null</code> if the specified code
* is not a primitive class code.
* @see java.lang.Class#getName()
*/
public static Class<?> getClassForCode(char classCode) {
for (Primitive primitive : PRIMITIVES) {
if (primitive.code == classCode) {
return primitive.javaClass;
}
}
return null;
}
/**
* Return the class code for the specified primitive class.
* Return <code>0</code> if the specified class
* is not a primitive class.
* @see java.lang.Class#getName()
*/
public static char getCodeForClass(Class<?> primitiveClass) {
if (( ! primitiveClass.isArray()) && (primitiveClass.getName().length() <= MAX_PRIMITIVE_CLASS_NAME_LENGTH)) {
for (Primitive primitive : PRIMITIVES) {
if (primitive.javaClass == primitiveClass) {
return primitive.code;
}
}
}
return 0;
}
// ********** instantiation **********
/**
* Convenience method.
* Return a new instance of the specified class,
* using the class's default (zero-argument) constructor.
* <p>
* <code>Class.newInstance()</code>
*/
public static Object newInstance(String className) {
return newInstance(className, null);
}
/**
* Return a new instance of the specified class,
* given the constructor parameter type and argument.
* <p>
* <code>Class.newInstance(Class<?> parameterType, Object argument)</code>
*/
public static Object newInstance(String className, Class<?> parameterType, Object argument) {
return newInstance(className, parameterType, argument, null);
}
/**
* Return a new instance of the specified class,
* given the constructor parameter types and arguments.
* <p>
* <code>Class.newInstance(Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static Object newInstance(String className, Class<?>[] parameterTypes, Object[] arguments) {
return newInstance(className, parameterTypes, arguments, null);
}
/**
* Convenience method.
* Return a new instance of the specified class,
* using the class's default (zero-argument) constructor.
* Use the specified class loader to load the class.
* <p>
* <code>Class.newInstance()</code>
*/
public static Object newInstance(String className, ClassLoader classLoader) {
return newInstance(classForName(className, false, classLoader));
}
/**
* Return a new instance of the specified class,
* given the constructor parameter type and argument.
* <p>
* <code>Class.newInstance(Class<?> parameterType, Object argument)</code>
*/
public static Object newInstance(String className, Class<?> parameterType, Object argument, ClassLoader classLoader) {
return newInstance(classForName(className, false, classLoader), parameterType, argument);
}
/**
* Return a new instance of the specified class,
* given the constructor parameter types and arguments.
* <p>
* <code>Class.newInstance(Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static Object newInstance(String className, Class<?>[] parameterTypes, Object[] arguments, ClassLoader classLoader) {
return newInstance(classForName(className, false, classLoader), parameterTypes, arguments);
}
/**
* Convenience method.
* Return a new instance of the specified class,
* using the class's default (zero-argument) constructor.
* <p>
* <code>Class.newInstance()</code>
*/
public static <T> T newInstance(Class<T> javaClass) {
return newInstance(javaClass, ZERO_PARAMETER_TYPES, ZERO_ARGUMENTS);
}
/**
* Convenience method.
* Return a new instance of the specified class,
* given the constructor parameter type and argument.
* <p>
* <code>Class.newInstance(Class<?> parameterType, Object argument)</code>
*/
public static <T> T newInstance(Class<T> javaClass, Class<?> parameterType, Object argument) {
return newInstance(javaClass, new Class[] {parameterType}, new Object[] {argument});
}
/**
* Return a new instance of the specified class,
* given the constructor parameter types and arguments.
* <p>
* <code>Class.newInstance(Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static <T> T newInstance(Class<T> javaClass, Class<?>[] parameterTypes, Object[] arguments) {
try {
return newInstance_(javaClass, parameterTypes, arguments);
} catch (InstantiationException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedConstructorSignature(javaClass, parameterTypes), ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedConstructorSignature(javaClass, parameterTypes), ex);
} catch (InvocationTargetException ex) {
throw new RuntimeException(buildFullyQualifiedConstructorSignature(javaClass, parameterTypes) + CR + ex.getTargetException(), ex);
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex + CR + buildFullyQualifiedConstructorSignature(javaClass, parameterTypes), ex);
}
}
/**
* Convenience method.
* Return a new instance of the specified class,
* using the class's default (zero-argument) constructor.
* <p>
* <code>Class.newInstance()</code>
*/
public static <T> T newInstance_(Class<T> javaClass)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
{
return newInstance_(javaClass, ZERO_PARAMETER_TYPES, ZERO_ARGUMENTS);
}
/**
* Convenience method.
* Return a new instance of the specified class,
* given the constructor parameter type and argument.
* <p>
* <code>Class.newInstance(Class<?> parameterType, Object argument)</code>
*/
public static <T> T newInstance_(Class<T> javaClass, Class<?> parameterType, Object argument)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
{
return newInstance_(javaClass, new Class[] {parameterType}, new Object[] {argument});
}
/**
* Return a new instance of the specified class,
* given the constructor parameter types and arguments.
* <p>
* <code>Class.newInstance(Class<?>[] parameterTypes, Object[] arguments)</code>
*/
public static <T> T newInstance_(Class<T> javaClass, Class<?>[] parameterTypes, Object[] arguments)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
{
return getConstructor_(javaClass, parameterTypes).newInstance(arguments);
}
// ********** type declarations **********
/**
* Return the class for the specified "type declaration".
*/
public static Class<?> getClassForTypeDeclaration(String typeDeclaration) {
return getClassForTypeDeclaration(typeDeclaration, null);
}
/**
* Return the class for the specified "type declaration".
*/
public static Class<?> getClassForTypeDeclaration_(String typeDeclaration)
throws ClassNotFoundException
{
return getClassForTypeDeclaration_(typeDeclaration, null);
}
/**
* Return the class for the specified "type declaration",
* using the specified class loader.
*/
public static Class<?> getClassForTypeDeclaration(String typeDeclaration, ClassLoader classLoader) {
TypeDeclaration td = buildTypeDeclaration(typeDeclaration);
return getClassForTypeDeclaration(td.elementTypeName, td.arrayDepth, classLoader);
}
/**
* Return the class for the specified "type declaration",
* using the specified class loader.
*/
public static Class<?> getClassForTypeDeclaration_(String typeDeclaration, ClassLoader classLoader)
throws ClassNotFoundException
{
TypeDeclaration td = buildTypeDeclaration(typeDeclaration);
return getClassForTypeDeclaration_(td.elementTypeName, td.arrayDepth, classLoader);
}
private static TypeDeclaration buildTypeDeclaration(String typeDeclaration) {
typeDeclaration = StringTools.removeAllWhitespace(typeDeclaration);
int arrayDepth = getArrayDepthForTypeDeclaration_(typeDeclaration);
String elementTypeName = getElementTypeNameForTypeDeclaration_(typeDeclaration, arrayDepth);
return new TypeDeclaration(elementTypeName, arrayDepth);
}
/**
* Return the array depth for the specified "type declaration"; e.g.<ul>
* <li><code>"int[]"</code> returns <code>1</code>
* <li><code>"java.lang.String[][][]"</code> returns <code>3</code>
* </ul>
*/
public static int getArrayDepthForTypeDeclaration(String typeDeclaration) {
return getArrayDepthForTypeDeclaration_(StringTools.removeAllWhitespace(typeDeclaration));
}
/**
* pre-condition: no whitespace in the type declaration.
*/
private static int getArrayDepthForTypeDeclaration_(String typeDeclaration) {
int last = typeDeclaration.length() - 1;
int depth = 0;
int close = last;
while (typeDeclaration.charAt(close) == ']') {
if (typeDeclaration.charAt(close - 1) == '[') {
depth++;
} else {
throw new IllegalArgumentException("invalid type declaration: " + typeDeclaration); //$NON-NLS-1$
}
close = last - (depth * 2);
}
return depth;
}
/**
* Return the element type name for the specified "type declaration"; e.g.<ul>
* <li><code>"int[]"</code> returns <code>"int"</code>
* <li><code>"java.lang.String[][][]"</code> returns <code>"java.lang.String"</code>
* </ul>
*/
public static String getElementTypeNameForTypeDeclaration(String typeDeclaration) {
typeDeclaration = StringTools.removeAllWhitespace(typeDeclaration);
return getElementTypeNameForTypeDeclaration_(typeDeclaration, getArrayDepthForTypeDeclaration_(typeDeclaration));
}
/**
* Return the element type name for the specified "type declaration"; e.g.<ul>
* <li><code>"int[]"</code> returns <code>"int"</code>
* <li><code>"java.lang.String[][][]"</code> returns <code>"java.lang.String"</code>
* </ul>
* Useful for clients that have already queried the type declaration's array depth.
*/
public static String getElementTypeNameForTypeDeclaration(String typeDeclaration, int arrayDepth) {
return getElementTypeNameForTypeDeclaration_(StringTools.removeAllWhitespace(typeDeclaration), arrayDepth);
}
/**
* pre-condition: no whitespace in the type declaration.
*/
private static String getElementTypeNameForTypeDeclaration_(String typeDeclaration, int arrayDepth) {
return typeDeclaration.substring(0, typeDeclaration.length() - (arrayDepth * 2));
}
/**
* Return the class for the specified "type declaration".
*/
public static Class<?> getClassForTypeDeclaration(String elementTypeName, int arrayDepth) {
return getClassForTypeDeclaration(elementTypeName, arrayDepth, null);
}
/**
* Return the class for the specified "type declaration".
*/
public static Class<?> getClassForTypeDeclaration_(String elementTypeName, int arrayDepth)
throws ClassNotFoundException
{
return getClassForTypeDeclaration_(elementTypeName, arrayDepth, null);
}
/**
* Return the class for the specified "type declaration",
* using the specified class loader.
*/
public static Class<?> getClassForTypeDeclaration(String elementTypeName, int arrayDepth, ClassLoader classLoader) {
try {
return getClassForTypeDeclaration_(elementTypeName, arrayDepth, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
/**
* Return the class for the specified "type declaration",
* using the specified class loader.
*/
// see the "Evaluation" of JDK bug 6446627 for a discussion of loading classes
public static Class<?> getClassForTypeDeclaration_(String elementTypeName, int arrayDepth, ClassLoader classLoader)
throws ClassNotFoundException
{
// primitives cannot be loaded via Class.forName(),
// so check for a primitive class name first
Primitive pcc = null;
if (elementTypeName.length() <= MAX_PRIMITIVE_CLASS_NAME_LENGTH) { // performance tweak
for (Primitive primitive : PRIMITIVES) {
if (primitive.javaClass.getName().equals(elementTypeName)) {
pcc = primitive;
break;
}
}
}
// non-array
if (arrayDepth == 0) {
return (pcc == null) ? Class.forName(elementTypeName, false, classLoader) : pcc.javaClass;
}
// array
StringBuilder sb = new StringBuilder(100);
for (int i = arrayDepth; i-- > 0; ) {
sb.append('[');
}
if (pcc == null) {
ClassName.append(elementTypeName, sb);
} else {
sb.append(pcc.code);
}
return Class.forName(sb.toString(), false, classLoader);
}
/**
* Return the class name for the specified "type declaration"; e.g.<ul>
* <li><code>"int"</code> returns <code>"int"</code>
* <li><code>"int[]"</code> returns <code>"[I"</code>
* <li><code>"java.lang.String"</code> returns <code>"java.lang.String"</code>
* <li><code>"java.lang.String[][][]"</code> returns <code>"[[[Ljava.lang.String;"</code>
* </ul>
* @see java.lang.Class#getName()
*/
public static String getClassNameForTypeDeclaration(String typeDeclaration) {
TypeDeclaration td = buildTypeDeclaration(typeDeclaration);
return getClassNameForTypeDeclaration(td.elementTypeName, td.arrayDepth);
}
/**
* Return the class name for the specified "type declaration".
* @see java.lang.Class#getName()
*/
public static String getClassNameForTypeDeclaration(String elementTypeName, int arrayDepth) {
// non-array
if (arrayDepth == 0) {
return elementTypeName;
}
if (elementTypeName.equals(ClassName.VOID_CLASS_NAME)) {
throw new IllegalArgumentException('\'' + ClassName.VOID_CLASS_NAME + "' must have an array depth of zero: " + arrayDepth + '.'); //$NON-NLS-1$
}
// array
StringBuilder sb = new StringBuilder(100);
for (int i = arrayDepth; i-- > 0; ) {
sb.append('[');
}
// look for a primitive first
Primitive pcc = null;
if (elementTypeName.length() <= MAX_PRIMITIVE_CLASS_NAME_LENGTH) { // performance tweak
for (Primitive primitive : PRIMITIVES) {
if (primitive.javaClass.getName().equals(elementTypeName)) {
pcc = primitive;
break;
}
}
}
if (pcc == null) {
ClassName.append(elementTypeName, sb);
} else {
sb.append(pcc.code);
}
return sb.toString();
}
// ********** exception messages **********
/**
* Return a string representation of the specified constructor.
*/
private static String buildFullyQualifiedConstructorSignature(Class<?> javaClass, Class<?>[] parameterTypes) {
return buildFullyQualifiedMethodSignature(javaClass, null, parameterTypes);
}
/**
* Return a string representation of the specified field.
*/
private static String buildFullyQualifiedFieldName(Class<?> javaClass, String fieldName) {
StringBuilder sb = new StringBuilder(200);
sb.append(javaClass.getName());
sb.append('.');
sb.append(fieldName);
return sb.toString();
}
/**
* Return a string representation of the specified field.
*/
private static String buildFullyQualifiedFieldName(Object object, String fieldName) {
return buildFullyQualifiedFieldName(object.getClass(), fieldName);
}
/**
* Return a string representation of the specified method.
*/
private static String buildFullyQualifiedMethodSignature(Class<?> javaClass, String methodName, Class<?>[] parameterTypes) {
StringBuilder sb = new StringBuilder(200);
sb.append(javaClass.getName());
// this check allows us to use this code for constructors, where the methodName is null
if (methodName != null) {
sb.append('.');
sb.append(methodName);
}
sb.append('(');
int max = parameterTypes.length - 1;
if (max != -1) {
// stop one short of the end of the array
for (int i = 0; i < max; i++) {
sb.append(parameterTypes[i].getName());
sb.append(", "); //$NON-NLS-1$
}
sb.append(parameterTypes[max].getName());
}
sb.append(')');
return sb.toString();
}
// ********** primitive constants **********
static final Iterable<Primitive> PRIMITIVES = buildPrimitives();
public static final char BYTE_CODE = 'B';
public static final char CHAR_CODE = 'C';
public static final char DOUBLE_CODE = 'D';
public static final char FLOAT_CODE = 'F';
public static final char INT_CODE = 'I';
public static final char LONG_CODE = 'J';
public static final char SHORT_CODE = 'S';
public static final char BOOLEAN_CODE = 'Z';
public static final char VOID_CODE = 'V';
static final int MAX_PRIMITIVE_CLASS_NAME_LENGTH = calculateMaxPrimitiveClassNameLength();
static final int MAX_PRIMITIVE_WRAPPER_CLASS_NAME_LENGTH = calculateMaxPrimitiveWrapperClassNameLength();
private static int calculateMaxPrimitiveClassNameLength() {
int max = -1;
for (Primitive primitive : PRIMITIVES) {
int len = primitive.javaClass.getName().length();
if (len > max) {
max = len;
}
}
return max;
}
private static int calculateMaxPrimitiveWrapperClassNameLength() {
int max = -1;
for (Primitive primitive : PRIMITIVES) {
int len = primitive.wrapperClass.getName().length();
if (len > max) {
max = len;
}
}
return max;
}
/**
* <strong>NB:</strong> <code>void.class.isPrimitive() == true</code>
*/
private static Iterable<Primitive> buildPrimitives() {
Primitive[] array = new Primitive[9];
array[0] = new Primitive(BYTE_CODE, java.lang.Byte.class);
array[1] = new Primitive(CHAR_CODE, java.lang.Character.class);
array[2] = new Primitive(DOUBLE_CODE, java.lang.Double.class);
array[3] = new Primitive(FLOAT_CODE, java.lang.Float.class);
array[4] = new Primitive(INT_CODE, java.lang.Integer.class);
array[5] = new Primitive(LONG_CODE, java.lang.Long.class);
array[6] = new Primitive(SHORT_CODE, java.lang.Short.class);
array[7] = new Primitive(BOOLEAN_CODE, java.lang.Boolean.class);
array[8] = new Primitive(VOID_CODE, java.lang.Void.class);
return new ArrayIterable<Primitive>(array);
}
// ********** member classes **********
static class Primitive {
final char code;
final Class<?> javaClass;
final Class<?> wrapperClass;
private static final String WRAPPER_CLASS_TYPE_FIELD_NAME = "TYPE"; //$NON-NLS-1$
// e.g. java.lang.Boolean.TYPE => boolean.class
Primitive(char code, Class<?> wrapperClass) {
this.code = code;
this.wrapperClass = wrapperClass;
this.javaClass = (Class<?>) getStaticFieldValue(wrapperClass, WRAPPER_CLASS_TYPE_FIELD_NAME);
}
}
private static class TypeDeclaration {
final String elementTypeName;
final int arrayDepth;
TypeDeclaration(String elementTypeName, int arrayDepth) {
this.elementTypeName = elementTypeName;
this.arrayDepth = arrayDepth;
}
}
// ********** suppressed constructor **********
/**
* Suppress default constructor, ensuring non-instantiability.
*/
private ReflectionTools() {
super();
throw new UnsupportedOperationException();
}
}