🎊 Android反射机制简单理解,ReflectionUtils  反射工具类

Android反射机制简单理解,ReflectionUtils  反射工具类

Android反射机制:什么是反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制(注意关键词:运行状态)换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods

反射机制主要提供的功能在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;java Reflection API简介Class类:代表一个类,位于java.lang包下Field类:代表类的成员变量(成员变量也称为类的属性)Method类:代表类的方法Constructor类:代表类的构造方法Array类:提供了动态创建数组,以及访问数组的元素的静态方法java中的Class介绍 Class 类十分特殊,它没有共有的构造方法,被jvm调用的(简单的理解:new对象或者被类加载器加载的时候),在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。

java中的Class三种获取方式利用对象调用getClass()方法获取该对象的Class实例;使用Class类的静态方法forName(),用类的名字获取一个Class实例 ;运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例; 说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。

代码语言:javascript复制 //方式一

Person person = new Person();

Class personClazz01 = person.getClass();

//方式二

try {

Class personClazz02 = Class.forName("Person");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

//方式三

Class personClazz03 = Person.class;

java中的Class中一些重要的方法 public Annotation[] getAnnotations () 获取这个类中所有注解

getClassLoader() 获取加载这个类的类加载器

getDeclaredMethods() 获取这个类中的所有方法

getReturnType() 获取方法的返回类型

getParameterTypes() 获取方法的传入参数类型

isAnnotation() 测试这类是否是一个注解类

getDeclaredConstructors() 获取所有的构造方法

getDeclaredMethod(String name, Class… parameterTypes) 获取指定的构造方法(参数:参数类型.class)

getSuperclass() 获取这个类的父类

getInterfaces() 获取这个类实现的所有接口

getFields() 获取这个类中所有被public修饰的成员变量

getField(String name) 获取指定名字的被public修饰的成员变量

newInstance() 返回此Class所表示的类,通过调用默认的(即无参数)构造函数创建的一个新实例

等等方法

代码语言:javascript复制invokeMethod :运行方法。下面是一个反射ReflectionUtils 反射工具类

代码语言:javascript复制package com.itep.mt.common.util;

/**

* Created by hx on 2019/7/12.

*/

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.lang.reflect.UndeclaredThrowableException;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.regex.Pattern;

/**

* Simple utility class for working with the reflection API and handling

* reflection exceptions.

*

*

Only intended for internal use.

*

* @author Juergen Hoeller

* @author Rob Harrop

* @author Rod Johnson

* @author Costin Leau

* @author Sam Brannen

* @author Chris Beams

* @since 1.2.2

*/

public abstract class ReflectionUtils {

/**

* Pattern for detecting CGLIB-renamed methods.

* @see #isCglibRenamedMethod

*/

private static final Pattern CGLIB_RENAMED_METHOD_PATTERN = Pattern.compile("CGLIB\\$(.+)\\$\\d+");

/**

* Attempt to find a {@link Field field} on the supplied {@link Class} with the

* supplied {@code name}. Searches all superclasses up to {@link Object}.

* @param clazz the class to introspect

* @param name the name of the field

* @return the corresponding Field object, or {@code null} if not found

*/

public static Field findField(Class clazz, String name) {

return findField(clazz, name, null);

}

/**

* Attempt to find a {@link Field field} on the supplied {@link Class} with the

* supplied {@code name} and/or {@link Class type}. Searches all superclasses

* up to {@link Object}.

* @param clazz the class to introspect

* @param name the name of the field (may be {@code null} if type is specified)

* @param type the type of the field (may be {@code null} if name is specified)

* @return the corresponding Field object, or {@code null} if not found

*/

public static Field findField(Class clazz, String name, Class type) {

//Assert.notNull(clazz, "Class must not be null");

//Assert.isTrue(name != null || type != null, "Either name or type of the field must be specified");

Class searchType = clazz;

while (!Object.class.equals(searchType) && searchType != null) {

Field[] fields = searchType.getDeclaredFields();

for (Field field : fields) {

if ((name == null || name.equals(field.getName())) && (type == null || type.equals(field.getType()))) {

return field;

}

}

searchType = searchType.getSuperclass();

}

return null;

}

/**

* Set the field represented by the supplied {@link Field field object} on the

* specified {@link Object target object} to the specified {@code value}.

* In accordance with {@link Field#set(Object, Object)} semantics, the new value

* is automatically unwrapped if the underlying field has a primitive type.

*

Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}.

* @param field the field to set

* @param target the target object on which to set the field

* @param value the value to set; may be {@code null}

*/

public static void setField(Field field, Object target, Object value) {

try {

field.set(target, value);

}

catch (IllegalAccessException ex) {

handleReflectionException(ex);

throw new IllegalStateException(

"Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage());

}

}

/**

* Get the field represented by the supplied {@link Field field object} on the

* specified {@link Object target object}. In accordance with {@link Field#get(Object)}

* semantics, the returned value is automatically wrapped if the underlying field

* has a primitive type.

*

Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}.

* @param field the field to get

* @param target the target object from which to get the field

* @return the field's current value

*/

public static Object getField(Field field, Object target) {

try {

return field.get(target);

}

catch (IllegalAccessException ex) {

handleReflectionException(ex);

throw new IllegalStateException(

"Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage());

}

}

/**

* Attempt to find a {@link Method} on the supplied class with the supplied name

* and no parameters. Searches all superclasses up to {@code Object}.

*

Returns {@code null} if no {@link Method} can be found.

* @param clazz the class to introspect

* @param name the name of the method

* @return the Method object, or {@code null} if none found

*/

public static Method findMethod(Class clazz, String name) {

return findMethod(clazz, name, new Class[0]);

}

/**

* Attempt to find a {@link Method} on the supplied class with the supplied name

* and parameter types. Searches all superclasses up to {@code Object}.

*

Returns {@code null} if no {@link Method} can be found.

* @param clazz the class to introspect

* @param name the name of the method

* @param paramTypes the parameter types of the method

* (may be {@code null} to indicate any signature)

* @return the Method object, or {@code null} if none found

*/

public static Method findMethod(Class clazz, String name, Class... paramTypes) {

//Assert.notNull(clazz, "Class must not be null");

//Assert.notNull(name, "Method name must not be null");

Class searchType = clazz;

while (searchType != null) {

Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());

for (Method method : methods)

if (name.equals(method.getName()) &&

(paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {

return method;

}

searchType = searchType.getSuperclass();

}

return null;

}

/**

* Invoke the specified {@link Method} against the supplied target object with no arguments.

* The target object can be {@code null} when invoking a static {@link Method}.

*

Thrown exceptions are handled via a call to {@link #handleReflectionException}.

* @param method the method to invoke

* @param target the target object to invoke the method on

* @return the invocation result, if any

* @see #invokeMethod(Method, Object, Object[])

*/

public static Object invokeMethod(Method method, Object target) {

return invokeMethod(method, target, new Object[0]);

}

/**

* Invoke the specified {@link Method} against the supplied target object with the

* supplied arguments. The target object can be {@code null} when invoking a

* static {@link Method}.

*

Thrown exceptions are handled via a call to {@link #handleReflectionException}.

* @param method the method to invoke

* @param target the target object to invoke the method on

* @param args the invocation arguments (may be {@code null})

* @return the invocation result, if any

*/

public static Object invokeMethod(Method method, Object target, Object... args) {

try {

return method.invoke(target, args);

}

catch (Exception ex) {

handleReflectionException(ex);

}

throw new IllegalStateException("Should never get here");

}

/**

* Invoke the specified JDBC API {@link Method} against the supplied target

* object with no arguments.

* @param method the method to invoke

* @param target the target object to invoke the method on

* @return the invocation result, if any

* @throws SQLException the JDBC API SQLException to rethrow (if any)

* @see #invokeJdbcMethod(Method, Object, Object[])

*/

public static Object invokeJdbcMethod(Method method, Object target) throws SQLException {

return invokeJdbcMethod(method, target, new Object[0]);

}

/**

* Invoke the specified JDBC API {@link Method} against the supplied target

* object with the supplied arguments.

* @param method the method to invoke

* @param target the target object to invoke the method on

* @param args the invocation arguments (may be {@code null})

* @return the invocation result, if any

* @throws SQLException the JDBC API SQLException to rethrow (if any)

* @see #invokeMethod(Method, Object, Object[])

*/

public static Object invokeJdbcMethod(Method method, Object target, Object... args) throws SQLException {

try {

return method.invoke(target, args);

}

catch (IllegalAccessException ex) {

handleReflectionException(ex);

}

catch (InvocationTargetException ex) {

if (ex.getTargetException() instanceof SQLException) {

throw (SQLException) ex.getTargetException();

}

handleInvocationTargetException(ex);

}

throw new IllegalStateException("Should never get here");

}

/**

* Handle the given reflection exception. Should only be called if no

* checked exception is expected to be thrown by the target method.

*

Throws the underlying RuntimeException or Error in case of an

* InvocationTargetException with such a root cause. Throws an

* IllegalStateException with an appropriate message else.

* @param ex the reflection exception to handle

*/

public static void handleReflectionException(Exception ex) {

if (ex instanceof NoSuchMethodException) {

throw new IllegalStateException("Method not found: " + ex.getMessage());

}

if (ex instanceof IllegalAccessException) {

throw new IllegalStateException("Could not access method: " + ex.getMessage());

}

if (ex instanceof InvocationTargetException) {

handleInvocationTargetException((InvocationTargetException) ex);

}

if (ex instanceof RuntimeException) {

throw (RuntimeException) ex;

}

throw new UndeclaredThrowableException(ex);

}

/**

* Handle the given invocation target exception. Should only be called if no

* checked exception is expected to be thrown by the target method.

*

Throws the underlying RuntimeException or Error in case of such a root

* cause. Throws an IllegalStateException else.

* @param ex the invocation target exception to handle

*/

public static void handleInvocationTargetException(InvocationTargetException ex) {

rethrowRuntimeException(ex.getTargetException());

}

/**

* Rethrow the given {@link Throwable exception}, which is presumably the

* target exception of an {@link InvocationTargetException}. Should

* only be called if no checked exception is expected to be thrown by the

* target method.

*

Rethrows the underlying exception cast to an {@link RuntimeException} or

* {@link Error} if appropriate; otherwise, throws an

* {@link IllegalStateException}.

* @param ex the exception to rethrow

* @throws RuntimeException the rethrown exception

*/

public static void rethrowRuntimeException(Throwable ex) {

if (ex instanceof RuntimeException) {

throw (RuntimeException) ex;

}

if (ex instanceof Error) {

throw (Error) ex;

}

throw new UndeclaredThrowableException(ex);

}

/**

* Rethrow the given {@link Throwable exception}, which is presumably the

* target exception of an {@link InvocationTargetException}. Should

* only be called if no checked exception is expected to be thrown by the

* target method.

*

Rethrows the underlying exception cast to an {@link Exception} or

* {@link Error} if appropriate; otherwise, throws an

* {@link IllegalStateException}.

* @param ex the exception to rethrow

* @throws Exception the rethrown exception (in case of a checked exception)

*/

public static void rethrowException(Throwable ex) throws Exception {

if (ex instanceof Exception) {

throw (Exception) ex;

}

if (ex instanceof Error) {

throw (Error) ex;

}

throw new UndeclaredThrowableException(ex);

}

/**

* 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} if the exception can be thrown as-is;

* {@code false} 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 (Class declaredException : declaredExceptions) {

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));

}

/**

* Determine whether the given method is an "equals" method.

* @see Object#equals(Object)

*/

public static boolean isEqualsMethod(Method method) {

if (method == null || !method.getName().equals("equals")) {

return false;

}

Class[] paramTypes = method.getParameterTypes();

return (paramTypes.length == 1 && paramTypes[0] == Object.class);

}

/**

* Determine whether the given method is a "hashCode" method.

* @see Object#hashCode()

*/

public static boolean isHashCodeMethod(Method method) {

return (method != null && method.getName().equals("hashCode") && method.getParameterTypes().length == 0);

}

/**

* Determine whether the given method is a "toString" method.

* @see Object#toString()

*/

public static boolean isToStringMethod(Method method) {

return (method != null && method.getName().equals("toString") && method.getParameterTypes().length == 0);

}

/**

* Determine whether the given method is originally declared by {@link Object}.

*/

public static boolean isObjectMethod(Method method) {

if (method == null) {

return false;

}

try {

Object.class.getDeclaredMethod(method.getName(), method.getParameterTypes());

return true;

}

catch (Exception ex) {

return false;

}

}

/**

* Determine whether the given method is a CGLIB 'renamed' method,

* following the pattern "CGLIB$methodName$0".

* @param renamedMethod the method to check

* @see //org.springframework.cglib.proxy.Enhancer#rename

*/

public static boolean isCglibRenamedMethod(Method renamedMethod) {

return CGLIB_RENAMED_METHOD_PATTERN.matcher(renamedMethod.getName()).matches();

}

/**

* Make the given field accessible, explicitly setting it accessible if

* necessary. The {@code setAccessible(true)} 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 Field#setAccessible

*/

public static void makeAccessible(Field field) {

if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) ||

Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {

field.setAccessible(true);

}

}

/**

* Make the given method accessible, explicitly setting it accessible if

* necessary. The {@code setAccessible(true)} 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 Method#setAccessible

*/

public static void makeAccessible(Method method) {

if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))

&& !method.isAccessible()) {

method.setAccessible(true);

}

}

/**

* Make the given constructor accessible, explicitly setting it accessible

* if necessary. The {@code setAccessible(true)} 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 Constructor#setAccessible

*/

public static void makeAccessible(Constructor ctor) {

if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers()))

&& !ctor.isAccessible()) {

ctor.setAccessible(true);

}

}

/**

* Perform the given callback operation on all matching methods of the given

* class and superclasses.

*

The same named method occurring on subclass and superclass will appear

* twice, unless excluded by a {@link MethodFilter}.

* @param clazz class to start looking at

* @param mc the callback to invoke for each method

* @see #doWithMethods(Class, MethodCallback, MethodFilter)

*/

public static void doWithMethods(Class clazz, MethodCallback mc) throws IllegalArgumentException {

doWithMethods(clazz, mc, null);

}

/**

* Perform the given callback operation on all matching methods of the given

* class and superclasses (or given interface and super-interfaces).

*

The same named method occurring on subclass and superclass will appear

* twice, unless excluded by the specified {@link MethodFilter}.

* @param clazz 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 clazz, MethodCallback mc, MethodFilter mf)

throws IllegalArgumentException {

// Keep backing up the inheritance hierarchy.

Method[] methods = clazz.getDeclaredMethods();

for (Method method : methods) {

if (mf != null && !mf.matches(method)) {

continue;

}

try {

mc.doWith(method);

}

catch (IllegalAccessException ex) {

throw new IllegalStateException("Shouldn't be illegal to access method '" + method.getName()

+ "': " + ex);

}

}

if (clazz.getSuperclass() != null) {

doWithMethods(clazz.getSuperclass(), mc, mf);

}

else if (clazz.isInterface()) {

for (Class superIfc : clazz.getInterfaces()) {

doWithMethods(superIfc, mc, mf);

}

}

}

/**

* 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 methods = new ArrayList(32);

doWithMethods(leafClass, new MethodCallback() {

public void doWith(Method method) {

methods.add(method);

}

});

return methods.toArray(new Method[methods.size()]);

}

/**

* Get the unique set of declared methods on the leaf class and all superclasses. Leaf

* class methods are included first and while traversing the superclass hierarchy any methods found

* with signatures matching a method already included are filtered out.

*/

public static Method[] getUniqueDeclaredMethods(Class leafClass) throws IllegalArgumentException {

final List methods = new ArrayList(32);

doWithMethods(leafClass, new MethodCallback() {

public void doWith(Method method) {

boolean knownSignature = false;

Method methodBeingOverriddenWithCovariantReturnType = null;

for (Method existingMethod : methods) {

if (method.getName().equals(existingMethod.getName()) &&

Arrays.equals(method.getParameterTypes(), existingMethod.getParameterTypes())) {

// Is this a covariant return type situation?

if (existingMethod.getReturnType() != method.getReturnType() &&

existingMethod.getReturnType().isAssignableFrom(method.getReturnType())) {

methodBeingOverriddenWithCovariantReturnType = existingMethod;

}

else {

knownSignature = true;

}

break;

}

}

if (methodBeingOverriddenWithCovariantReturnType != null) {

methods.remove(methodBeingOverriddenWithCovariantReturnType);

}

if (!knownSignature && !isCglibRenamedMethod(method)) {

methods.add(method);

}

}

});

return methods.toArray(new Method[methods.size()]);

}

/**

* Invoke the given callback on all fields in the target class, going up the

* class hierarchy to get all declared fields.

* @param clazz the target class to analyze

* @param fc the callback to invoke for each field

*/

public static void doWithFields(Class clazz, FieldCallback fc) throws IllegalArgumentException {

doWithFields(clazz, fc, null);

}

/**

* Invoke the given callback on all fields in the target class, going up the

* class hierarchy to get all declared fields.

* @param clazz 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 clazz, FieldCallback fc, FieldFilter ff)

throws IllegalArgumentException {

// Keep backing up the inheritance hierarchy.

Class targetClass = clazz;

do {

Field[] fields = targetClass.getDeclaredFields();

for (Field field : fields) {

// Skip static and final fields.

if (ff != null && !ff.matches(field)) {

continue;

}

try {

fc.doWith(field);

}

catch (IllegalAccessException ex) {

throw new IllegalStateException(

"Shouldn't be illegal to access field '" + field.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 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 filter methods to be operated on by a method callback.

*/

public 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 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 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()));

}

};

/**

* Pre-built MethodFilter that matches all non-bridge methods.

*/

public static MethodFilter NON_BRIDGED_METHODS = new MethodFilter() {

public boolean matches(Method method) {

return !method.isBridge();

}

};

/**

* Pre-built MethodFilter that matches all non-bridge methods

* which are not declared on {@code java.lang.Object}.

*/

public static MethodFilter USER_DECLARED_METHODS = new MethodFilter() {

public boolean matches(Method method) {

return (!method.isBridge() && method.getDeclaringClass() != Object.class);

}

};

}

🎯 相关推荐

英雄联盟杰斯是谁 英雄联盟未来守护者杰斯:英雄定位与技能深度解析
红米手机内存卡怎么安装
365速发在线注册

红米手机内存卡怎么安装

📅 01-01 👀 8275
墨族降临!《完美世界》新版本“撼世王朝”公测_手机网易网