目录
一. 问题
啥是反射?
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
现实生活中,如果不是接触了Java,大概突然问下这个概念,大多人都答不上来,现实生活中有没有类似的案例呢?
按照我的理解,简单的做个感性比喻(严格意义上,是不贴切的),一辆车在高速公路上正向行驶,表达正常的运行,一辆车在高速公路上逆向行驶,表达非正常运行;
交通规定,高速公路上,逆向行驶被电子警察拍到,就会导致12 分 + 罚款,严重的可能导致刑事拘留;
我们可以这样简单的认为,非正常逆向行驶车辆到政策性惩罚的过程(可被各种解释和条例覆盖),被解释为反射,各种规定提供各种规章制度和法律条文+罚款性措施,具备条例工具性;高速公路上,行驶的车辆,具有实体性;
实体性运动到工具性的析构过程称之为反射;
计算机世界里,一切都是0101...,计算机世界到人类世界一切都是映射,映射是计算机世界和人类世界关联的本质;
...
我们可以使用有限的规则和制度,来描述无限的世界边界;
网上对反射有如下解释:
推荐:
1. JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2. 所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。
3. 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
侧重点:
- 自描述
- 可检测
...
其实,如果想要对反射有个透彻了解,需要去深入了解Java 内存模型,还需要对类加载器有个基本的认识,这个是不可避免绕不过去的; 本文不讨论那么深入,本人也没那个能力,简单讨论一下从反射的概念工具性角度去认识,了解一些基础方面即可;
虚拟机中类的生命周期:加载,连接(验证,准备,解析),初始化,使用,卸载。
如果深入了解反射,需要的知识储备:
- JAVA 内存模型
- JVM 构建实例过程
- 类加载器机制
- 反射 API
- 基础概念和理论实践
二. 意义和作用
一问,反射有啥用呢?
Reflection 是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期 Reflection APIs 取得任何已知名称之 class 的内部信息,包括 package、type parameters、superclass、implemented interfaces、inner classes, outer class, fields、constructors、methods、modifiers,并可于执行期生成instances、变更 fields 内容或唤起 methods。
我们都知道,Java 是面向对象编程语言;
对象 = 成员属性 + 成员方法;
扩展给出面向过程:
程序 = 算法 + 数据结构;
请牢记上述公式;
二问,反射有啥用呢?
用自己的话,归纳总结一下:
- 类的结构性,(结构信息[所属类,成员属性,成员方法,...])
- 类的数据性,(数据信息,[类对象,...])
- 对象的功能性,(功能信息,[所属类,成员属性,成员方法,...])
- 对象的行为性,(行为信息,[方法调用,方法执行,...])
- 数据结构信息化,(元信息,可描述,可自洽性,可工具性,...)
三. 反射机制的载体
序列 | 包名 | 类名 | 描述 | 备注 |
---|---|---|---|---|
1 | java.lang.Class | Class | 代表类的类类型,在运行的Java应用程序中表示类和接口 | |
2 | Constructor | 代表类的构造方法类型 | ||
3 | Field | 代表类的成员属性类型 | ||
4 | Method | 代表类的成员方法类型 |
注意:
带有
Declared
修饰的方法可以反射到 私有方法 ,没有Declared
修饰的只能用来反射 公有方法 ;
3.1 Class
获取Class 有三种方式:
- x.class;
- x.getClass();
- Class.forName("...");
Class 相关的方法:
方法 | 描述 | 备注 |
asSubclass() | 强制转换该 Class 对象,以表示指定的 class 对象所表示的类的一个子类。 | |
cast() | 将一个对象强制转换成此 Class 对象所表示的类或接口。 | |
getClasses() | 返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。 | |
forName() | 返回与带有给定字符串名的类或接口相关联的 Class 对象。 | |
getAnnotation() | 如果存在该元素的指定类型的注解,则返回这些注解,否则返回 null。 | |
getConstructor() | 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 | |
getDeclaredAnnotation() | 返回直接存在于此元素上的所有注解。 | |
getDeclaredConstructor() | ||
getDeclaredField() | ||
getDeclaredMethod() | ||
getField() | ||
getMethod() | ||
getResource() | ||
getResourceAsStream() | ||
isAnnotationPresent() | ||
isAssignableFrom() | ||
isInstance() | ||
newInstance() | ||
toGenericString() | ||
toString() | ||
getClassLoader() | 返回该类的类加载器。 |
后续补上,注释
代码示例:
public void reflect_case_class() {
String className = "";
// 1. x.class
className = BaseBean.class.getSimpleName();
System.out.println(String.format("className: %s", className));
// 2. x.getClass()
className = BaseBean.newInstance().getClass().getSimpleName();
System.out.println(String.format("className: %s", className));
// 3. Class.forName()
try {
Class<?> clazz = Class.forName("com.dovsnier.java.sample.bean.BaseBean");
if (null != clazz) {
className = clazz.getSimpleName();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(String.format("className: %s", className));
}
执行结果:
className: BaseBean
className: BaseBean
className: BaseBean
3.2 Constructor
3.3 Fieid
3.4 Method
...
持续性补充
...
四. 参考
- https://www.iteye.com/blog/zlb1986-937781;
- https://www.zhihu.com/topic/19596531/hot;
- https://www.zhihu.com/question/24304289;
- https://docs.oracle.com/javase/8/docs/api/;
- https://tool.oschina.net/apidocs/apidoc?api=jdk-zh;
(完)