反射
反射,是框架设计的灵魂,几乎所有的框架都必须要用到这个点,但是使用它的前提条件是拿到对应的Class字节码,Class类用于表示.class文件。
反射的概念
反射就是在Java运行期间,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法或者获取它的属性,这种能够动态获取的信息以及动态调用对象的方法的功能,叫作Java的反射机制。
大白话解释反射
在解释之前,必须得先搞清楚Class类是啥,Class类就是描述类信息的一个东西,Class类表示.class文件。
反射是什么?弄清这个问题之前,我们得先要确认一件事情,就是Java里面处处是对象,毕竟Java是面向对象的语言,那么怎么理解反射呢,反射起始就是通过获取一个类的描述文件进而去获取这个类的一切信息。可以理解为Java就是一个容器,它把你需要的类(.class文件)一个个都去加载到了JVM中,你想要获取这个类的时候就去向JVM要就完事了,这个设计思想起始和Spring IOC容器非常相似,而反射干活就是找到.class文件对应的Class类,然后通过这个类的描述信息去获取这个类的所有信息。
感兴趣的可以去看看Class这个类的文档,这里就不多说了。
反射的使用
前面说了,Java万物皆是对象,那么类中的【方法】、【属性】等都有对应的类去描述,下面去介绍。
描述方法的类——Method
描述属性的类——Field
反射的使用方式
- 获取Class对象
1.1 获取Class对象的三种方式
- getClass();
- 任何数据类型(包括基本数据类型)都有一个class属性
- 通过Class的静态方法——forName(String className)
最后一个是最常使用的,在JDBC连接数据库的时候就能经常看到Class.forName()方法。
// 1 获取Class
object.getClass();
// 2
object.class
// 3
Class.forName("com.xiaoming.Object")
- 通过反射获取构造方法并调用
// 获取所有的公有构造方法
Constructor[] conArray[] = object.getConstructors();
// 获取所有的构造方法 包括公有、私有、受保护
Constructor[] conArray[] = object.getDeclaredConstructors();
// 获取公有、无参的构造方法
Constructor constructor = object.getConstructor(null)
// 调用构造方法
Object objetc = constructor.newInstance();
// 调用私有构造方法
constructor.setAccessible(true)// 暴力访问(忽略修饰符)
obj = constructor.newInstance();
- 通过反射获取属性、调用其方法和上述类似,就不描述了,学会举一反三
- 反射还有一个非常重要的特性,就是可以越过泛型检查
import java.lang.reflect.Method;
import java.util.ArrayList;
/*
* 通过反射越过泛型检查
*
* 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?
*/
public class Demo {
public static void main(String[] args) throws Exception{
ArrayList<String> strList = new ArrayList<>();
strList.add("a");
strList.add("b");
//获取ArrayList的Class对象,反向的调用add()方法,添加数据
Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
//获取add()方法
Method m = listClass.getMethod("add", Object.class);
//调用add()方法
m.invoke(strList, 100);
//遍历集合
for(Object obj : strList){
System.out.println(obj);
}
}
}
控制台输出如下:
a
b
100