大聪明教你学Java | 深入浅出聊Java的反射机制

260 阅读4分钟

前言

一起养成写作习惯!这是我参与「掘金日新计划 · 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 反射类中的方法

首先先简单介绍下常用的几个方法。

  1. Method[] getMethods() 获取类中被public修饰的所有方法
  2. Method getMethod(Stringname, Class…<?> paramTypes) 根据名字和参数类型获取对应方法,该方法必须被public修饰
  3. Method[] getDeclaredMethods() 获取所有方法,但无法获取继承下来的方法
  4. MethodgetDeclaredMethod(String name, Class…<?> paramTypes) 根据名字和参数类型获取对应方法,无法获取继承下来的方法

下面举一个简单的例子 首先先在Animal类中增加一个带参的方法,如下所示:

	public void m1(String name) {
        System.out.println("这里有一只" + name);
    }

接下来反射这个带参的方法 在这里插入图片描述

2.2.1 反射类中的属性字段

首先先简单介绍下常用的几个方法。

  1. Field[] getFields() 获取类中所有被public修饰的所有变量
  2. Field getField(String name) 根据变量名获取类中的一个变量,该变量必须被public修饰
  3. Field[] getDeclaredFields() 获取类中所有的变量,但无法获取继承下来的变量
  4. Field getDeclaredField(String name) 根据姓名获取类中的某个变量,无法获取继承下来的变量

下面举一个简单的例子 在Animal类中定义一个属性并为其赋值

	public String name = "小狗";

接下来反射这个name字段 在这里插入图片描述 以上内容就是对反射的简单的应用示例。

3.反射的应用场景

1.JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类
2.框架的代码里经常需要利用反射来操作对象的set、get方法,来把程序的数据封装到Java对象中去。
3.框架中的注解。
......

小结

反射是框架的灵魂,理解了反射机制才能更深入的学习框架。 以上内容是我对反射的一个浅析,如果文章中有错误,欢迎大家留言指正;若您有更好、更简便的方式或理念,欢迎您在留言区留下您的意见建议。

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西