一、什么是反射?
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
简单来说,就是java反射机制可以在运行阶段,基于编译阶段的class对象,动态的创建对象,获取类的完整结构。
二、反射的使用
定义一个类:
public class ReflectionDemo {
public String username;
private Integer password ;
public ReflectionDemo() {
}
public ReflectionDemo(String name) {
System.out.println(name);
}
public void say() {
System.out.println("hello!");
}
public void talk(String name, Integer age) {
System.out.println(name + "今年:" + age + "岁!");
}
}
获取类型
/**
* 获取类对象的三种方式
*/
//1.通过对象的getClass()方法获取
ReflectionDemo rd = new ReflectionDemo();
Class<? extends ReflectionDemo> aClass = rd.getClass();
System.out.println("通过对象的getClass()方法获取:"+aClass);
//2.通过类名的class
Class<? extends ReflectionDemo> aClass1 = ReflectionDemo.class;
System.out.println("通过类名的class: "+aClass1);
//3.通过Class.forName()
try {
Class<?> aClass2 = Class.forName("com.my.reflection.ReflectionDemo");
System.out.println("Class.forName():"+aClass2);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
运行结果:
通过对象的getClass()方法获取:class com.my.reflection.ReflectionDemo
通过类名的class: class com.my.reflection.ReflectionDemo
Class.forName():class com.my.reflection.ReflectionDemo
获取属性
/**
* 反射 获取成员变量
* Field getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
* Field[] getFields() 返回具有public属性的成员变量的数组
* Field getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
* Field[] getDelcaredFields() 返回所有成员变量组成的数组(不分public和非public属性)
*/
Class class4 = null;
try {
//获取类对象
class4 = Class.forName("com.my.reflection.ReflectionDemo");
//获取属性
Field field1 = class4.getField("username");
System.out.println("field1=" + field1.getName());
Field field2 = class4.getDeclaredField("password");
System.out.println("field2=" + field2.getName());
System.out.println("*******************");
// 使用getFields获取属性
Field[] fields = class4.getFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("*******************");
// 使用getDeclaredFields获取属性
fields = class4.getDeclaredFields();
for (Field f : fields) {
System.out.println(f);
}
运行结果:
field1=username
field2=password
*******************
public java.lang.String com.my.reflection.ReflectionDemo.username
*******************
public java.lang.String com.my.reflection.ReflectionDemo.username
private java.lang.Integer com.my.reflection.ReflectionDemo.password
获取类的方法
/**
* 反射 调用 对象方法
* Method getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法
* Method[] getMethods() 返回所有具有public属性的方法数组
* Method getDeclaredMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
* Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
*/
Class class3 = null;
try {
class3 = Class.forName("com.my.reflection.ReflectionDemo");
Method method = class3.getMethod("talk", String.class,Integer.class);
Object object = class3.newInstance();
method.invoke(object, "老王",18);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
运行结果:
老王今年:18岁!
获取类的Constructor
/**
* 反射通过无惨构造实例对象
*/
Class class1 = null;
try {
class1 = Class.forName("com.my.reflection.ReflectionDemo");
Object object = class1.newInstance();
ReflectionDemo reflectionDemo = (ReflectionDemo) object;
reflectionDemo.say();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
/**
* 反射通过构造实例对象
* Constructor getConstructor(Class[] params)根据构造函数的参数,返回一个具体的具有public属性的构造函数
* Constructor getConstructors() 返回所有具有public属性的构造函数数组
* Constructor getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
* Constructor getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
*/
Class class2 = null;
try {
class2 = Class.forName("com.my.reflection.ReflectionDemo");
Constructor constructor = class2.getConstructor(String.class);
Object object = constructor.newInstance("abc");
ReflectionDemo reflectionDemo = (ReflectionDemo) object;
reflectionDemo.say();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
运行结果
hello!
abc
hello!
动态Proxy
java.lang.reflect.Proxy
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类
InvocationHandler
是代理实例的调用处理程序 实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
UserService接口
public interface UserService {
String getName(String name);
}
UserService实现
public class UserServiceImpl implements UserService {
public String getName(String name) {
System.out.println(name);
return "getName";
}
}
MyInvocationHandler代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* jdk动态代理
* @author onereader
*/
public class MyInvocationHandler implements InvocationHandler {
//目标对象
private Object target;
public MyInvocationHandler() {
super();
}
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (method.getName().equals("getName")) {
System.out.println("++++++before " + method.getName() + "++++++");
Object result = method.invoke(target, args);
System.out.println("++++++after " + method.getName() + "++++++");
return result;
} else {
Object result = method.invoke(target, args);
return result;
}
}
}
MainTest 类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler invoke = new MyInvocationHandler(userService);
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(), invoke);
System.out.println(userServiceProxy.getName("123"));
}
}
运行结果:
++++++before getName++++++
123
++++++after getName++++++
getName
三、总结
对于反射,简单来说就是可以再运行时,可以获取到这个类的完整信息。并且创建一个满足自己需要的对象,进行操作。总的来说,学会后使用起来真心很方便~~~ 至于反射的不好地方,我这里不熬诉了,有兴趣自行百度学习~