反射?
如何使用Java类和对象?
设计类----> 创建对象----> 使用对象调用方法或属性。
反序列化
如果只知道类名,能否动态得到类的定义信息,包括那些属性,方法等。
答:通过反射获得。
**反射:**在程序运行过程中,可以动态获取类的信息,以及创建类的对象,以及调用对象中的属性和方法。
**作用:**动态获取类的信息
**好处:**写一个方法,可以处理任何的类
类名,类在项目中的地址,通过地址找到类,就可动态获得类中信息。
自己的项目,在那使用,在哪new,会将代码写死,框架需要处理不同的类,都需要能够进行处理,mybatis框架可以写一个方法,接收一个类的地址,就可以根据地址创建该类的对象,
反射基本用法
如何动态类的信息
User.class --> User.class --> 一旦程序中使用User类,就会加载字节码文件,为该类创建一个Class对象,通过该类的Class类的对象,获得类中的信息。
获得Class类对象
public static void main(String[] args) throws ClassNotFoundException {
/*
获得 类的Class对象
*/
//1.通过对象名获取到类的Class对象
User user=new User();
Class c1=user.getClass();
//2.通过类名.class获取到类的Class对象
Class c2=User.class;
//3.通过 Class.forName("类的地址")
Class c3=Class.forName("com.ffyc.javareflect.User");
System.out.println(c1==c2);//true
System.out.println(c1==c3);//true
}
获取构造方法
获得到Class对象后, 如何获得类的信息,获得那些信息
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//类的地址
//通过类的地址 加载类
String name="com.ffyc.javareflect.User";
Class c=Class.forName(name);
//获得无参构造,获得公共权限的构造方法
//通过无参的构造方法,创建对象
Constructor constructor=c.getConstructor();
Object user=constructor.newInstance();
//获得有参构造
Constructor constructor1=c.getConstructor(int.class,String.class);
Object user1=constructor1.newInstance(1,"jim");
//获得私有的
Constructor constructor2=c.getDeclaredConstructor();
//设置对私有权限机型操作
constructor2.setAccessible(true);
Object car=constructor2.newInstance();
System.out.println(car);
car 无参构造
com.ffyc.javareflect.Car@1b6d3586
}
获取属性
String name="com.ffyc.javareflect.User";//类的地址
Class c=Class.forName(name);//通过类的地址 加载类
Constructor constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
Object object=constructor.newInstance();
/*
获得类中的属性
getFileld(name) 获得的是 指定名称 公共权限属性
getFields() 获得所有 公共权限属性
getDeclaredField(name) 获得指定名称 私有权限属性
getDeclaredFields 获得所有 私有和公共
*/
Field[] declaredFields = c.getDeclaredFields();//类中所有属性
System.out.println(declaredFields.length);
for(Field f:declaredFields){
System.out.println(f.getName());
}
//模拟查询数据结果
Map<String,Object> map=new HashMap<>();
map.put("id",100);
map.put("name","tom");
for(Field f:declaredFields){
//f.set(object,map.get(f.getName())); 键值
f.setAccessible(true);
f.set(object,map.get(f.getName()));
}
System.out.println(object);
获取成员方法
method.invoke(object,100);
相当于 object.setId(100)
String name="com.ffyc.javareflect.User";//类的地址
Class c=Class.forName(name);//通过类的地址 加载类
Constructor constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
Object object=constructor.newInstance();
/*
getMethods()获得类中所有公共的成员方法
getMethod("getId",type) 获得共的 指定名称参数的成员方法
getDeclaredMethods() 获得所有成员方法 包含私有
getDeclaredMethod("getId",type) 指定名称参数的成员方法
*/
Method method=c.getMethod("setId", int.class);
method.invoke(object,100);
System.out.println(object);
练习–将 object–>Json
public class Test5 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
User user=new User(100,"王博");
Car car=new Car(101,"wb");
String u=objectToJson(user);
String c=objectToJson(car);
System.out.println(u);
System.out.println(c);
}
//我们选择用 属性名 进行改造的方式,拿到get方法再调用
public static String objectToJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String s="{";
Class c=object.getClass();
//获得所有属性
Field[] declaredFields = c.getDeclaredFields();
for(Field f:declaredFields){
//f.getName() 获得属性名
//c.getMethod 获得指定名称的get方法
// invoke 调用 方法
s+=f.getName()+":"+c.getMethod(check(f.getName())).invoke(object)+",";
}
s=s.substring(0,s.length()-1);
s+="}";
return s;
}
// 将获取到的id 转为 getId
//fieldName.charAt(0) 获取第一个字母
//toUpperCase() 将小写转为 大写
//fieldName.substring(1); 截取字符串 从第 1 位截取到最后一位
public static String check(String fieldName){
String methodName="get"+String.valueOf(fieldName.charAt(0)).toUpperCase()+fieldName.substring(1);
return methodName;
}
}