前序
在我们没有学习框架之前我们都是通给new来创建对象,如:创建一个我们已知的对象
Car car=new Car();
调用类中的成员变量和成员方法都是对象直接调用。
在学习了mybatis框架后,我们了解到可以通过类名,能动态得到类中定义的信息,包括类中有哪些方法,有哪些属性等
比如在xml映射文件中:
<mapper namespace="com.ffyc.mybatispro.dao.AdminDao"></mapper>
通过这个我们就知道调用的这给类中的接口
以及
<select id="findAdminByid" parameterType="int" resultType="Admin">select * from admin where id =#{id} </select>
在这里mybatis框架中就会把查询到的数据映射到Admin这个类中,在这里我们就会产生一个疑惑为什么这样呢?
实际上市MyBatis在底层中实现了java反射机制。那什么是java反射机制,下面是一个简单的入门级的介绍。
反射机制概念
在运行状态中,在仅知道一给类名时,就可以动态获得类中信息,创建类对象,调用对象成员的机制就称为Java反射机制。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个 方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为 java语言的反射机制
作用:动态获取类的信息
Class类
Java.lang.Class
Class类的对象,表示当前正在运行中的类和接口,Class类是实现java反射的基础
一旦class文件被加载到内存,就会为其创建一个Class对象。任意类使用都会创建Class对象
Java反射相关API
Java反射机制的相关类主要有:
Class类,Constructor类 获得构造方法,Method类 获得方法,Field类 获得属性
获得Class对象
通过全类名获得Class对象(有三种方法)
String classname="com.ffyc.javaReflect.User";
方式一:通过Class类中的属性formname(String classname)(Class类的静态方法)
Class clazz=Class.forName(classname);
方式二:类名.class,适用于通过类名获得Class对象
//方式2 Class clazz2 = User.class;
方式三:Object类中的getClass方法:适用于通过对象获得Class实例的情况
//方式3 User user=new User(); Class clazz3 = user.getClass();
获得相应类的构造方法
有四种方式
Class aClass=Class.forName(classname);
通过Class类中的getConstructor()获得相应类的构造方法
//获得类的构造方法,通过构造方法api中的方法创建对象Constructor constructor1 = aClass.getConstructor();//获得指定的公共构造方法
String.class表示:参数是String类型(这里需要什么类型,转换成什么即可)
Constructor constructor2 = aClass.getConstructor(String.class,String.class);//获得有参构造方法
getConstructors()获得所有公共的构造方法放到Constructor数组中
Constructor [] constructors=aClass.getConstructors();//获得所有公共的构造方法
getDeclaredConstructor()和getDeclaredConstructors()
//虽然可以获得私有构造方法,但是一般不建议操作私有成员,因为打破了封装性 aClass.getDeclaredConstructor();//获得类中任意构造方法,包括私有的 aClass.getDeclaredAnnotations();//获得类中所有构造方法,包括私有的
获得相应类的方法
有四种方式
参数表示是类方法的名称
Method method = aClass.getMethod(String name)
其它三个获取类方法的方式
//获得类中所有公共的成员方法,返回值是一个Method类数组 aClass.getMethods(); //获得类中的任意成员方法,包括私有的,返回值是一个Method类 aClass.getDeclaredMethod("eat"); //获得类中所有成员方法,包括私有的,返回值是一个Method类数组 aClass.getDeclaredMethods();
调用方法执行程序,这里的object表示要通过那个对象来调用这个方法
//调用方法使用invoke调用 method.invoke(object );
获得类的成员变量
有四种方式
方式一
Field accountField= aClass.getField("account");//获得指定名称的公共成员变量
方式二
Field accountField= aClass.getDeclaredField("account");//获得指定名称的成员变量,包含私有的
方式三
Field[] fields= aClass.getDeclaredFields();//获得类中所有的成员变量,包含私有的
方法四
Field[] fields1=aClass.getFields();//获得类中所有公共的成员变量
如果想要操作私有变量,则需要setAccessible(true),改为false则程序报错
f.setAccessible(true);//允许访问操作私有变量
模拟在数据库查询到数据,赋值给对象
//模拟数据库中查到的数据HashMap<String,String> map=new HashMap<>();map.put("account","admin");map.put("password","111"); Field[] fields= aClass.getDeclaredFields();//获得类中所有的成员变量,包含私有的for (Field f:fields){f.setAccessible(true);//允许访问操作私有变量f.set(object,map.get(f.getName()));}System.out.println(object);
结果:
为了能够更好的熟悉Java反射机制练习俩个实例
第一个,给私有成员变量赋值,不使用可以操作私有的属性的方法,
package com.ffyc.javaReflect;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;public class Test5 {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {//使用反射机制时,只知道类的名称(包名+类名)String classname="com.ffyc.javaReflect.Car";//1、通过类名获得类的Class对象Class aClass=Class.forName(classname);//通过类的Class对象来创建对象Object object = aClass.newInstance();//通过属性的set、get对私有属性赋值HashMap<String,String> map=new HashMap<>();map.put("name","奔驰");map.put("color","白色");//先拿到类中的所有私有属性Field[] fields= aClass.getDeclaredFields();for (Field field:fields){//根据属性名生成set方法名称String setMethod ="set"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);System.out.println(setMethod);//通过class对象,获得对应的set方法对象Method setMethodObj =aClass.getMethod(setMethod,field.getType());//调用set方法setMethodObj.invoke(object,map.get(field.getName()));}System.out.println(object);}
}
第二个是一个简单转为json字符串
package com.ffyc.javaReflect;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class ToJsonUtil {public static String toJson(Object object1) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {Class aClass=object1.getClass();String json="{";//获取类中的属性变量Field [] fields= aClass.getDeclaredFields();for (Field field:fields){String getMethod="get"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);//拿到get方法Method method = aClass.getMethod(getMethod);//调用get方法String value = (String) method.invoke(object1);json+=field.getName()+":"+value+",";}json=json.substring(0,json.length()-1);json+="}";return json;}public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {User user=new User();user.setAccount("admin");user.setPassword("111");Car car=new Car("奔驰","白色");System.out.println(toJson(user));System.out.println(toJson(car));}
}