反射就是把Java类中的各个成分映射成一个个的Java对象,通常将反射与代理杰哥,构造新工具。
Java中主要由以下的类来实现Java反射机制
1.Class.forName("全类名")
,将字节码文件加载仅内存,获取Class对象。通过将forName
与newInstance
配合使用,调用默认构造器初始化一个新的对象,如果该类没有默认构造器会抛出异常。但是目前newInstance
方法已经是被JDK15标注为不推荐使用,它会在编译期跳过异常检查,推荐使用Constructor类中的newInstance()
方法。
String s = "java.util.Random";
Object m = Class.forName(s).newInstance();
2.类名.class
,通过类名的属性class获取Class对象
3.对象.getClass()
,getClass
()方法定义于Object类中
public final native Class<?> getClass();
4.xxxClassLoader.loadClass()
通过类加载器传入类路径获取
Class<?> loadClass(String name);
值得注意的是,类加载器获取Class对象仅仅为类加载过程中的加载阶段,因此没有涉及类的准备阶段和初始化阶段,因此类中的静态变量不会赋值(准备阶段),静态代码块和类构造器不会执行(初始化阶段)
获取成员变量
Field[] getFields(); //获取所有public成员变量
Field getField(String name); //获取指定字段名的public成员变量
Field[] getDeclaredFields(); //获取所有成员变量,不考虑是否为public
Field getDeclaredField(String name); //获取指定字段名的成员变量,不考虑是否为public
获取构造方法
Constructor<?>[] getConstructors();
Constructor<T> getConstructor(Class<?>... parameterTypes);
Constructor<?>[] getDeclaredConstructors();
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);
获取成员方法
Method[] getMethods();
Method getMethod(String name, Class<?>... parameterTypes);
Method[] getDeclaredMethods();
Method getDeclaredMethod(String name, Class<?>... parameterTypes);
获取全类名
String getName();
设置访问限制符
setAccessible(boolean flag);
设置值
set(Object obj, Object value);
set(Object obj, int value);
set(Object obj, char value);
...
获取值
Object get(Object obj);
int getInt(Object obj);
char getChar(Object obj);
...
设置访问限制符
setAccessible(boolean flag);
通过参数指定构造方法构造一个对象
public T newInstance(Object ... initargs);
设置访问限制符
setAccessible(boolean flag);
执行方法
public Object invoke(Object obj, Object... args);
JDK动态代理使用:继承InvocationHandler接口,以及实现其中的invoke()
方法
public interface SmsService {
String send(String message);
}
public class SmsServiceImpl implements SmsService {
public String send(String message) {
System.out.println("send message:" + message);
return message;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DebugInvocationHandler implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private final Object target;
public DebugInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
//调用方法之前,我们可以添加自己的操作
System.out.println("before method " + method.getName());
Object result = method.invoke(target, args);
//调用方法之后,我们同样可以添加自己的操作
System.out.println("after method " + method.getName());
return result;
}
}