天天看点

通过模拟Mybatis的自动封装来理解反射什么是反射

Java反射入门

  • 什么是反射
    • 用new关键字创建对象
    • 使用反射创建对象
    • 使用反射动态调用方法
    • 总结

什么是反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

以上就是对反射的解释,但是解释的太官方,现在我们从代码入手。先看不用反射的情况应该怎么创建对象

用new关键字创建对象

比如现在通过JDBC查询出来了一个结果集ResultSet,需要将结果集转化成对象之后返回。

Student student = new Student();
student.setName(resultSet.getString("name"));
return student;
           

这样写没什么问题,可是如果查询另外一个实体,这个地方就是“死”的了,只能再写类似的代码,将Student换成Teacher,能不能通过某种形式将创建对象和调用方法的过程动态化呢?很显然,使用new关键字的话不能动态实例化,而反射就能做到这一点

使用反射创建对象

现在通过反射的方式,传入字符串形式的参数,通过这个字符串进行实例化

Class<?> cls = Class.forName("com.jack.reflect.Student");
Object object = cls.newInstance();
           

这样就可以通过com.jack.reflect.Student这个字符串作为变量,进行实例化了,打印看一下

通过模拟Mybatis的自动封装来理解反射什么是反射

和用new关键字效果相同,这就是反射的第一步!!

那么第二步,可以动态创建对象,肯定也可以动态调用方法,实例化的是A类就调用A类的方法,实例化的是B类就调用B类的方法,这样一来,代码就变得非常非常灵活了!开始上代码

使用反射动态调用方法

这里我们来模拟一下Mybatis,用过Mybatis的都知道,它可以帮我们自动封装好实体类然后返回,那让我们来自己模拟实现一下。

//1.使用集合模拟jdbc查询的resultSet
Map resultSet = new HashMap<String,String>();
resultSet.put("name", "张三");
resultSet.put("age", "21");

//2.动态加载对象,这里的动态可以理解喂配置文件    
Class<?> cls = Class.forName("com.jack.reflect.Student");
Object object = cls.newInstance();

//3.通过反射获取该对象的方法,获取的是一个集合
Method[] methods = cls.getMethods();

//4.获取结果集的keySet
Set<String> set = resultSet.keySet();
Iterator<String> iterator = set.iterator();

//迭代“结果集”
while (iterator.hasNext()) {
	//获取结果集中的“字段”
    String next = iterator.next();
    //将每一个结果集的属性拼接成setXxxx的形式,比如name就变成setName
    String methodName = Util.toBeSet(next);
    //遍历方法集中的每一个方法
    for (Method method :
            methods) {
        //如果该类的方法中有这个methodName,通过反射调用进行赋值,可以理解为调用和methodName这个字符串“长得一样”的方法
        if (methodName.equals(method.getName())) {
        	/*比如这里通过反射获取到的方法集合中有一个setName()方法,结果集中有一个name字段,
        	通过Util.toBeSet()这个方法将name字段变为“setName”这一字符串,
        	那么匹配到之后就可以通过反射的invoke方法调用真正的setName()方法*/
            method.invoke(object,resultSet.get(next));
        }
    }
}

System.out.println(object);

           

Util.toBeSet().java

/**
 * @author Jinkang He
 * @version 1.0
 * @date 2020/7/27 9:10
 */

public class Util {
    public static String toBeSet(String str) {
        String result = null;
        String substring = str.substring(0, 1);
        String s = substring.toUpperCase();
        result = "set" + s + str.substring(1,str.length());
        return result;
    }
}
           

运行看一下效果

通过模拟Mybatis的自动封装来理解反射什么是反射

可以看到我们没有写死代码,只要通过配置文件或者其他方式读取到需要封装的全限定名,就可以给任何遵循了JavaBean规范的实体类进行属性的自动装配了

总结

如果让我用一句话来总结反射的话,那么就是使用字符串的形式来动态创建对象,获取属性,调用方法,这也就是开头反射定义里面的运行状态中,框架之所以可以给任何人使用都利用了反射来支撑,因为框架的开发者不知道你会写什么,只能在你写好之后使用反射的机制进行动态操作。

本人能力有限,文章中若有遗落或有错误,欢迎大家指出纠正,共同交流进步。