前言
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。
🍊支持作者: 点赞👍、关注💖、留言💌~
反射在日常开发的过程中使用的频率并不是很高,但是在开发框架或者搞一些底层代码时就会经常看到反射的影子,所以身为大聪明的我们还是得对反射有一定的了解,以此来帮助我们更快的学习框架和底层代码。
Java的反射机制
1.“正射”
既然有反射机制那肯定有一个与之相对的“正射”,其实“正射”就是直接new一个对象
Map<String, String> map = new HashMap<>();
map.put("大聪明","大聪明学Java");
大聪明用“正射”的方式new了一个Map对象,这时候突然发现用LinkedHashMap更好,大聪明只能咔哧咔哧改代码
Map<String, String> map = new LinkedHashMap<>();
map.put("大聪明","大聪明咔哧咔哧改代码");
功能马上上线了,这时候组长突然对大聪明说~ 组长:这里不能用LinkedHashMap,应该改成TreeMap!!!! 大聪明:¥%……&……&#¥%#¥#!!&(&
Map<String, String> map = new LinkedHashMap<>();
map.put("大聪明","大聪明继续咔哧咔哧改代码");
修改了两次代码后,大聪明终于静下心来思考:对于这种情况,有没有办法不修改这么多代码呢? 那不是必须滴嘛,这时候就该让反射登场了
2.浅析反射
首先说一下什么是反射,反射就是把Java类中的各个部分,映射成一个个的Java对象,拿到这些对象后可以去做一些你想做的事情。一个类一般是由构造函数、方法、成员变量(字段/属性)三部分组成,利用反射技术可以把这些组成部分映射成一个个对象。 可能上面的概念有些抽象,先举个简单的例子
public Map<String, String> getMap(String cName) {
//返回与带有给定字符串名的类或接口相关联的Class对象
Class c = Class.forName(cName);
Constructor constructor = c.getConstructor();
return (Map<String, String>) constructor.newInstance();
}
这时候无论你需要什么样的Map,你只需要传入对应Map的全路径名就可以了,想用HashMap就传入java.util.HashMap,想用TreeMap就传入java.util.TreeMap。
2.1 反射构造方法
首先我们先写一个类
public class Animal {
//无参构造方法
public Animal(){
System.out.println("这是一个无参的构造方法");
}
//一个参数的构造方法
public Animal(String name){
System.out.println("小动物是" + name);
}
//两个参数的构造方法
public Animal(String name, String food){
System.out.println("小动物是" + name + ",它爱吃" + food);
}
//私有构造方法
private Animal(int num){
System.out.println("这里有" + num + "只小狗");
}
}
2.1.1 反射无参的构造方法
从上边的例子看出,成功的执行了无参的构造函数。
需要注意的是,要想反射,第一步就是得到类的字节码。
简单说一下得到类的字节码的几种方式
(1)、Class.forName("com.ziye.exGirlfriend.test.Animal"); 也就是上图中的方式
(2)、对象.getClass();
(3)、类名.class;
2.1.2 反射“一个参数”/“两个个参数”的构造函数
2.1.3 反射私有构造函数
需要注意的是,在反射私有构造方法时需要使用Constructor constructor = c.getDeclaredConstructor(int.class);的方式去读取私有函数,并设置constructor.setAccessible(true);暴力反射
2.2 反射类中的方法或属性字段
2.2.1 反射类中的方法
首先先简单介绍下常用的几个方法。
- Method[] getMethods() 获取类中被public修饰的所有方法
- Method getMethod(Stringname, Class…<?> paramTypes) 根据名字和参数类型获取对应方法,该方法必须被public修饰
- Method[] getDeclaredMethods() 获取所有方法,但无法获取继承下来的方法
- MethodgetDeclaredMethod(String name, Class…<?> paramTypes) 根据名字和参数类型获取对应方法,无法获取继承下来的方法
下面举一个简单的例子 首先先在Animal类中增加一个带参的方法,如下所示:
public void m1(String name) {
System.out.println("这里有一只" + name);
}
接下来反射这个带参的方法
2.2.1 反射类中的属性字段
首先先简单介绍下常用的几个方法。
- Field[] getFields() 获取类中所有被public修饰的所有变量
- Field getField(String name) 根据变量名获取类中的一个变量,该变量必须被public修饰
- Field[] getDeclaredFields() 获取类中所有的变量,但无法获取继承下来的变量
- Field getDeclaredField(String name) 根据姓名获取类中的某个变量,无法获取继承下来的变量
下面举一个简单的例子 在Animal类中定义一个属性并为其赋值
public String name = "小狗";
接下来反射这个name字段
以上内容就是对反射的简单的应用示例。
3.反射的应用场景
1.JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类
2.框架的代码里经常需要利用反射来操作对象的set、get方法,来把程序的数据封装到Java对象中去。
3.框架中的注解。
......
小结
反射是框架的灵魂,理解了反射机制才能更深入的学习框架。 以上内容是我对反射的一个浅析,如果文章中有错误,欢迎大家留言指正;若您有更好、更简便的方式或理念,欢迎您在留言区留下您的意见建议。
本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇
希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)
如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。
爱你所爱 行你所行 听从你心 无问东西