反射机制
- 运行时加载,探知,使用编译期间完全未知的类。
- 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用他的任意一个方法和属性。
- jvm加载完类之后,在堆内存中,就产生了一个对应的Class类型的对象,这个对象就包含了完整的类的结构信息。Class(大写c)是一个类。
- 一个类只有一个Class反射对象。
反射的使用
首先定义一个类User作为例子
package Reflection;
public class User {
public int id;
private int age;
String name;
public User(){
}
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
有三种方式来获得某一个类的Class对象
/方式1
Class<?> demo1 = Class.forName(path);
//方式2
Class demo2 = Reflection.User.class;
//方式3
Class demo3 = path.getClass();
获取类的名字
demo1.getName();//获得类名+包名
demo1.getSimpleName();//获得类名
获得属性信息
Field[] fields1 = demo1.getFields();//只能获得public的属性
Field[] fields2 = demo1.getDeclaredFields();//获得所有属性
Field field3 = demo1.getDeclaredField("name");//获取指定属性
获取方法信息同属性,把Field换为Method
如果方法有参数,必须传入参数类型对应的Class对象
Method method = demo1.getDeclaredMethod("setAge", int.class);
通过反射API调用构造方法,构造对象
User u1 = (User)demo1.newInstance();//其实是调用了User的无参构造
Constructor constructor = demo1.getDeclaredConstructor(int.class,int.class,String.class);
User u2 = (User) constructor.newInstance(001,18,"yst");//利用有参构造,利用newInstance传参
通过反射API调用普通方法,好处是可以动态的调用方法,例如从其他地方传过来再放到参数中
User u3 = (User)demo1.newInstance();
Method method2 = demo1.getDeclaredMethod("setName", String.class);
method2.invoke(u3,"yst222");
通过反射API操作属性
因为定义age属性为private,所以set不能访问,要用setAccessible取消安全检查
User u4 = (User)demo1.newInstance();
Field f = demo1.getDeclaredField("age");
f.setAccessible(true);
f.set(u4,22);
反射性能
经过测试,使用反射调用方法所用时间远大于直接调用方法,所以当需要频繁调用反射的时候可以取消安全检查,这样使效率提高4倍。
Class.setAccessible(true); 这样就可以取消安全检查。
反射操作泛型
package Reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class ReflectionGenerics {
public void test1(Map<String,Reflection.User> map, List<Reflection.User> list){
System.out.println("test1");
}
public Map<Integer,Reflection.User>test2(){
System.out.println("test2");
return null;
}
public static void main(String[] args) {
try {
//获得指定方法参数泛型信息
Method m = ReflectionGenerics.class.getMethod("test1",Map.class,List.class);
//获得泛型参数类型
Type[] t = m.getGenericParameterTypes();
for (Type x: t) {
System.out.println("#"+x);
//如果是一个参数类型
if(x instanceof ParameterizedType){
//强制类型转换
Type[] genericTypes = ((ParameterizedType)x).getActualTypeArguments();
for(Type y : genericTypes){
System.out.println("泛型类型:"+y);
}
}
}
//获得指定方法返回值泛型信息
Method m2 = ReflectionGenerics.class.getMethod("test02", null);
Type returnType = m2.getGenericReturnType();
if(returnType instanceof ParameterizedType){
Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
for (Type genericType : genericTypes) {
System.out.println("返回值,泛型类型:"+genericType);
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}