反射-学会了更上一层楼

反射是Java中的一种强大的工具,允许程序在运行时检查和操作类、接口、字段和方法。通过反射,我们可以动态地创建对象、调用方法和访问/修改字段,无需预先知道具体的类信息。文章举例说明了反射在JDBC中用于读取数据库配置和SpringMVC中的自动装配,提高了代码的灵活性和降低了耦合度。
摘要由CSDN通过智能技术生成

想要理解反射,我认为一定要从底层开始理解才能真正懂得什么是反射。

首先我们写好的.java文件在经过编译后会转换为.class文件存入JVM的方法区内,现在我们要知道.class字节码文件中都有什么,这个文件中存有我们类中的所有属性方法以及构造器,甚至修饰符等等,除了注解以外的要素都有,都映射在JVM的方法区内。

好,现在我们提出反射的原理,反射就是将.class字节码文件中的所有要素都看成对象,所以现在,我要通过反射操作去获取到类中的方法属性和构造器,有没有可能。答案是有!我们都把这些元素看成对象了,我凭什么不能拿,凭什么不能改,能!!!

我们该怎么获取到这些东西呢?

我们想改.class文件中的内容,首先我们要获得调用内容的对象吧,一般我们是怎么获得对象的

new 一个对象();

但在反射里我们怎么做的

//首先我们要获得这个类
                                      //这里是完整的包名到类名
Class<ReflectTest> ref = Class.forName("com.atAchao.reflect.ReflectTest");
Object refInstance = ref.getConstrctor().newInstance();

这里refInstance就是当前的对象,但我们并不能直接像原来写代码一样,直接通过对象.方法调用方法,因为我们此时调用的方法,参数等等都存在JVM的方法区中,不通过.Class类对象是取不出来的。

//这里我们需要ref对象去获取类内的方法和属性等等
 Method method = ref.getMethod("方法名", String.class);

得到方法之后,通过invoke方法来使用方法

method.invoke(调用对象, 具体参数);

我们介绍完了反射大概怎么用,现在要知道具体的方法

以下方法都是通过Class类对象调用的

Method[] getMethods();
获得类内所有非私有方法,以及父类的非私有方法

Method[] getDeclaredMethods();
【暴力】获得类内所有方法,包括私有方法,但不包括父类中的任何方法

Method getMethod(String methodName, Class... parameterTypes);
获得类内methodName方法,并提供参数列表的【类型.class】参数

Method getDeclaredMethod(String methodName, Class... parameterTypes);
【暴力】获得类内methodName方法,并提供参数列表的【类型.class】参数

Object invoke(Object obj, Object... parameterValues);
这里通过上面两个方法对象调用invoke方法,传入第一个参数为想要调用方法的真正对象,之后为具体参数

Field[] getFields();
获得类内所有参数,返回值类型为数组

Field[] getDeclaredFields(); 
【暴力】获得类内所有参数,返回值类型为数组

Field getField(String fieldName);
获取类内一个指定参数

Field getDeclaredField(String fieldName); 
【暴力】获取类内一个指定参数

void set(Object obj, Object value); 
这里通过上面两个属性对象调用set方法,传入第一个参数为想要调用方法的真正对象,之后为具体值

Object get(Object obj); 
这里也是通过上面两个属性对象调用get方法,参数为想要调用方法的真正对象

void setAccessible(boolean flag); 
反射操作中 Constructor, Method ,Field 对象都可以调用该方法解决 私有化反射对象权限操作问题
这个方法是在暴力获取到方法后给予方法权限,使之能正常运行

public static void setAccessible(AccessibleObject[] array, boolean flag) 
AccessibleObject 类工具方法,所需参数是 AccessibleObject 数组和对应的权限标记,flag 通常为 true。
Field Method Constructor 都是 AccessibleObject 子类

反射的用途,为什么搞这么复杂,比new一个对象复杂多了,所以到底在哪能用到反射呢

我认为用反射的原因在于,提高代码的灵活性,降低耦合度,并且能很好的提高代码的复用性,同时反射能隐藏掉很多细节,让使用者有刚好的体验

举几个例子吧

例子一:JDBC

Class.forName("com.mysql.jdbc.Driver");

//获取与数据库连接的对象-Connetcion
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java001", "root", "root");

//获取执行sql语句的statement对象
statement = connection.createStatement();

//执行sql语句,拿到结果集
resultSet = statement.executeQuery("SELECT * FROM users");

后来变成了下面的样子

//获取配置文件的读入流
InputStream inputStream = UtilsDemo.class.getClassLoader()
                            .getResourceAsStream("db.properties");

Properties properties = new Properties();
properties.load(inputStream);

//获取配置文件的信息
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");

//加载驱动类
Class.forName(driver);

为什么变成这样呢,原因很简单,不想一行一行的看,找出要修改的地方,一行一行的修改,这样很麻烦,我把要改的地方写在配置文件里,统一修改不香吗,我想换数据库换数据库,我想改密码改密码,但读取配置文件的核心代码我一点也不用变,代码变灵活,降低耦合度,接口式编程,形成一套代码能对应多种配置文件。

例子二:写Serlvet

//通过html的name属性,获取到值
String username = request.getParameter("username");
String password = request.getParameter("password");
String gender = request.getParameter("gender");

//复选框和下拉框有多个值,获取到多个值
String[] hobbies = request.getParameterValues("hobbies");
String[] address = request.getParameterValues("address");

//获取到文本域的值
String description = request.getParameter("textarea");

springMVC怎么写的呢

@RequestMapping(value = "/bean")
@ResponseBody
public String missionSave(Config config) {
    
       String name= config.getName();
}

自动装配,这是怎么实现的,就是通过反射实现的,通过字段名与参数名相同来自动获得相应的值,隐藏了许多细节,用户体验更好了。

其实在开发过程中,使用反射的机会真的不多,但一般我们在做自己的框架或组件的时候,就要用到反射了。

如有不足,私信或者评论指正,肥肠感激。🙋

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值