reflectionutils.java
来自「spring framework 2.5.4源代码」· Java 代码 · 共 561 行 · 第 1/2 页
JAVA
561 行
}
/**
* Throws an IllegalStateException with the given exception as root cause.
* @param ex the unexpected exception
*/
private static void handleUnexpectedException(Throwable ex) {
// Needs to avoid the chained constructor for JDK 1.4 compatibility.
IllegalStateException isex = new IllegalStateException("Unexpected exception thrown");
isex.initCause(ex);
throw isex;
}
/**
* Determine whether the given method explicitly declares the given exception
* or one of its superclasses, which means that an exception of that type
* can be propagated as-is within a reflective invocation.
* @param method the declaring method
* @param exceptionType the exception to throw
* @return <code>true</code> if the exception can be thrown as-is;
* <code>false</code> if it needs to be wrapped
*/
public static boolean declaresException(Method method, Class exceptionType) {
Assert.notNull(method, "Method must not be null");
Class[] declaredExceptions = method.getExceptionTypes();
for (int i = 0; i < declaredExceptions.length; i++) {
Class declaredException = declaredExceptions[i];
if (declaredException.isAssignableFrom(exceptionType)) {
return true;
}
}
return false;
}
/**
* Determine whether the given field is a "public static final" constant.
* @param field the field to check
*/
public static boolean isPublicStaticFinal(Field field) {
int modifiers = field.getModifiers();
return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers));
}
/**
* Make the given field accessible, explicitly setting it accessible if necessary.
* The <code>setAccessible(true)</code> method is only called when actually necessary,
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
* @param field the field to make accessible
* @see java.lang.reflect.Field#setAccessible
*/
public static void makeAccessible(Field field) {
if (!Modifier.isPublic(field.getModifiers()) ||
!Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
field.setAccessible(true);
}
}
/**
* Make the given method accessible, explicitly setting it accessible if necessary.
* The <code>setAccessible(true)</code> method is only called when actually necessary,
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
* @param method the method to make accessible
* @see java.lang.reflect.Method#setAccessible
*/
public static void makeAccessible(Method method) {
if (!Modifier.isPublic(method.getModifiers()) ||
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
method.setAccessible(true);
}
}
/**
* Make the given constructor accessible, explicitly setting it accessible if necessary.
* The <code>setAccessible(true)</code> method is only called when actually necessary,
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
* @param ctor the constructor to make accessible
* @see java.lang.reflect.Constructor#setAccessible
*/
public static void makeAccessible(Constructor ctor) {
if (!Modifier.isPublic(ctor.getModifiers()) ||
!Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) {
ctor.setAccessible(true);
}
}
/**
* Perform the given callback operation on all matching methods of the
* given class and superclasses.
* <p>The same named method occurring on subclass and superclass will
* appear twice, unless excluded by a {@link MethodFilter}.
* @param targetClass class to start looking at
* @param mc the callback to invoke for each method
* @see #doWithMethods(Class, MethodCallback, MethodFilter)
*/
public static void doWithMethods(Class targetClass, MethodCallback mc) throws IllegalArgumentException {
doWithMethods(targetClass, mc, null);
}
/**
* Perform the given callback operation on all matching methods of the
* given class and superclasses.
* <p>The same named method occurring on subclass and superclass will
* appear twice, unless excluded by the specified {@link MethodFilter}.
* @param targetClass class to start looking at
* @param mc the callback to invoke for each method
* @param mf the filter that determines the methods to apply the callback to
*/
public static void doWithMethods(Class targetClass, MethodCallback mc, MethodFilter mf)
throws IllegalArgumentException {
// Keep backing up the inheritance hierarchy.
do {
Method[] methods = targetClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (mf != null && !mf.matches(methods[i])) {
continue;
}
try {
mc.doWith(methods[i]);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException(
"Shouldn't be illegal to access method '" + methods[i].getName() + "': " + ex);
}
}
targetClass = targetClass.getSuperclass();
}
while (targetClass != null);
}
/**
* Get all declared methods on the leaf class and all superclasses.
* Leaf class methods are included first.
*/
public static Method[] getAllDeclaredMethods(Class leafClass) throws IllegalArgumentException {
final List list = new ArrayList(32);
doWithMethods(leafClass, new MethodCallback() {
public void doWith(Method method) {
list.add(method);
}
});
return (Method[]) list.toArray(new Method[list.size()]);
}
/**
* Invoke the given callback on all fields in the target class,
* going up the class hierarchy to get all declared fields.
* @param targetClass the target class to analyze
* @param fc the callback to invoke for each field
*/
public static void doWithFields(Class targetClass, FieldCallback fc) throws IllegalArgumentException {
doWithFields(targetClass, fc, null);
}
/**
* Invoke the given callback on all fields in the target class,
* going up the class hierarchy to get all declared fields.
* @param targetClass the target class to analyze
* @param fc the callback to invoke for each field
* @param ff the filter that determines the fields to apply the callback to
*/
public static void doWithFields(Class targetClass, FieldCallback fc, FieldFilter ff)
throws IllegalArgumentException {
// Keep backing up the inheritance hierarchy.
do {
// Copy each field declared on this class unless it's static or file.
Field[] fields = targetClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
// Skip static and final fields.
if (ff != null && !ff.matches(fields[i])) {
continue;
}
try {
fc.doWith(fields[i]);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException(
"Shouldn't be illegal to access field '" + fields[i].getName() + "': " + ex);
}
}
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
}
/**
* Given the source object and the destination, which must be the same class
* or a subclass, copy all fields, including inherited fields. Designed to
* work on objects with public no-arg constructors.
* @throws IllegalArgumentException if the arguments are incompatible
*/
public static void shallowCopyFieldState(final Object src, final Object dest) throws IllegalArgumentException {
if (src == null) {
throw new IllegalArgumentException("Source for field copy cannot be null");
}
if (dest == null) {
throw new IllegalArgumentException("Destination for field copy cannot be null");
}
if (!src.getClass().isAssignableFrom(dest.getClass())) {
throw new IllegalArgumentException("Destination class [" + dest.getClass().getName() +
"] must be same or subclass as source class [" + src.getClass().getName() + "]");
}
doWithFields(src.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
makeAccessible(field);
Object srcValue = field.get(src);
field.set(dest, srcValue);
}
}, COPYABLE_FIELDS);
}
/**
* Action to take on each method.
*/
public static interface MethodCallback {
/**
* Perform an operation using the given method.
* @param method the method to operate on
*/
void doWith(Method method) throws IllegalArgumentException, IllegalAccessException;
}
/**
* Callback optionally used to method fields to be operated on by a method callback.
*/
public static interface MethodFilter {
/**
* Determine whether the given method matches.
* @param method the method to check
*/
boolean matches(Method method);
}
/**
* Callback interface invoked on each field in the hierarchy.
*/
public static interface FieldCallback {
/**
* Perform an operation using the given field.
* @param field the field to operate on
*/
void doWith(Field field) throws IllegalArgumentException, IllegalAccessException;
}
/**
* Callback optionally used to filter fields to be operated on by a field callback.
*/
public static interface FieldFilter {
/**
* Determine whether the given field matches.
* @param field the field to check
*/
boolean matches(Field field);
}
/**
* Pre-built FieldFilter that matches all non-static, non-final fields.
*/
public static FieldFilter COPYABLE_FIELDS = new FieldFilter() {
public boolean matches(Field field) {
return !(Modifier.isStatic(field.getModifiers()) ||
Modifier.isFinal(field.getModifiers()));
}
};
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?