反射
一、反射是什么?
反射 (reflect)、在javav的java.lang.reflect包下,反射是java为我们提供的一种操作字节码文件的类库。
二、反射的用处?
通过反射机制可以动态的在程序运行时获取字节码文件(.class文件),并且针对字节码文件进行读取、修改等操作,实现动态的操作类,反射也是OOP原则的重要实现方式。大多数框架中都应用了反射,例如SSM三大框架等,
三、如何使用反射
如果要使用反射,首先需要知道反射中重要的类有那些。以及如何通过反射获取Class文件。
!!!!本文章只展示常用的基本的方法,其他方法请查看javaAPI文档
!!!!以下示例未包含获取匿名内部类的方法和枚举的方法,他日再补充
0. 反射判断类型
首先判断文件的类型(可能有些鸡肋)你也可以不用。
Class c = Class.forName("java.util.Map");
c.isInterface();//判断文件是否为 接口 类型
c.isAnnotation();//判断文件是否为 注解 类型
c.isEnum();//判断文件是否为 枚举 类型
//....
1. 反射相关类
相关类 | 作用 |
---|---|
java.lang.class | 字节码类 ,代表了整体的字节码文件 |
java.reflect.Constructor | 字节码中的构造方法的字节码 ,代表了字节码中的构造方法 |
java.reflect.Field | 字节码中的属性的字节码,代表了属性 |
java.reflect.Method | 字节码中的方法的字节码,代表类中的方法 |
2.通过反射获取类三种方式
第一种:
通过java.lang.class包下的静态方法: **forName(String s)**获取,
优点: 这种方法比较通用,可以获取绝大多的class对象,只要能读到路径就能获取。
缺点: 就是不能读取到类路径之外的
java方法:
public static Class<?> forName(String className)
throws ClassNotFoundException{
//........
}
使用示例:
Class<?> s = Class.forName("java.long.String");//获取String类的class对象
关于路径:
有时我们需要保证类在多种环境下的路径中也能被正确的找到,所以我们需要一种通用的方法,这种方法可以获取并且只能获取类路径(即:src目录为类路径根路径)下的类文件。
方法:
String path = Thread.currentThread().getContextClassLoader()
.getResource("全限定路径.后缀") //从根开始例如:com/ccnn/resource/a.properties 获取类时后缀为.class
.getPath();
//Thread.currentThread() ---->获取当前线程对象
//getContextClassLoader() ---->获取线程对象的类加载器对象
//getResource("文件名.后缀") ---->类加载器默认从当前根路径下作为起点加载资源
//getPath(); ---->获取路径
//直接以流的形式返回
InputStream inputStream= Thread.currentThread().getContextClassLoader().getResourceAsStream("全限定路径.后缀"); //直接以流的形式返回
path 即为获取到的类的 绝对 路径。
小知识点:
在执行Class.forName("java.long.String");
时会进行类加载,而静态代码块只会在类加载时执行,并且只会执行一次,
第二种:
在java中任何一个对象都拥有 getClass() 方法 通过对象 .getClass() 就能获取到类的Class字节码对象。
java方法:
public final native Class<?> getClass();
//所有类都默认继承了Object超类,也就默认继承了此方法。
使用示例:
Date time = new Date();
Class<?> c = time.getClass();//获取Date类的class对象
第三种:
在java中任何一个“数据类型”都拥有 Class 属性 通过对象 .Class 就能获取到数据类型的 Class字节码对象。
使用示例: