前序
在我们没有学习框架之前我们都是通给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));
}
}