Java反射
Java反射的理解
Java的反射机制就是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能调用它的任意一个方法,无需在编译期确定具体的类和方法,而是在运行的时候通过字符串动态决定。
反射机制就是一种动态获取信息以及动态调用对象方法的功能。
正射
与反射相对应的就是正射,其实这也不是什么java的官方术语,只是相对于反射口头叫出来的说法。
正射就是Java最普通最直接的调用方式:在写代码时就明确指定类、方法和对象,通过new创建实例、用点.调用方法,所有类型和调用关系在编译期就已经确定,由编译器负责检查是否正确,而不是等到运行期再去动态查找。
在编写代码时,当需要使用到某一个类的时候,都会先了解这个类是做什么的。然后实例化这个类,接着用实例化好的对象进行操作,这就是正射。
1 | |
Student student = new Student();
- 第一个
Student是类型名,定义的变量将来指向的是Student类型的对象 student是变量名,就是一个标识符用来在代码里表示这个对象- 第二个
Student()是构造方法调用,用来创建一个真正的Student对象
先实例化一个student对象,然后调用doHomework方法,这段代码在还没有运行的时候就已经知道其中要运行的类是student和调用的方法是doHomework
反射
反射就是,一开始并不知道我们要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了
1 | |
这里就是获取了一个Student的原型,然后通过这个原型得到这个类的所有元信息(所有属性和方法)
这段代码是整个程序运行的时候,从字符串reflection.Student中才知道要操作的是类是Student
反射的作用
- 让Java具有动态性:Java作为强类型语言,在代码编译时,对于已编译好的代码就不能改变了,而不像PHP中的eval(“任意代码”);的动态执行(就是传入什么就执行什么),但可以通过反射进行改变,比如修改已有对象的属性
- 动态生成对象
- 动态调用方法
- 操作内部类和私有类
Class对象
**RTTI**运行时类型识别就是在程序运行过程中,识别一个对象的类型和类的信息
Java在运行时识别对象和类的信息的方式有两种:第一种就是传统的RTTI,它假定我们在编译期已知了所有类型;另一种就是反射机制,它允许我们在运行时才发现和使用类的信息。
每个类都有一个Class对象,当编译一个新类就会产生一个Class对象(也就是被保存在一个同名的.class文件中)
其实更直观的就是在IDEA中创建一个Java类文件,命名为Test

文件开头用 class定义一个 Test 类型,在其中写代码,当JVM加载这个类时,会在内存中创建一个同名的Class对象,这个Class对象就保存了Test类相关的类型信息

Class类的对象作用时运行时提供或获得某个对象的类型信息
反射的基本使用
获取Class类对象
创建reflection包,在包中创建TestReflection类
方法一:使用Class.forName静态方法
1 | |
forName方法存在于Class类中,会返回传入值的原型类
方法二:使用类的.class方法
1 | |
方法三:使用实例对象的getClass()方法
1 | |
利用getName输出,只返回纯粹的类名

反射就是操作获得的class对象
从原型class类中实例化对象
方法一:使用newInstance,无参构造
1 | |
方法二:使用getConstructor,有参构造
1 | |

这里就可以更进一步理解反射,先拥有原型class3,再调用其中的方法比如getConstructor
获取类中的属性
方法一:使用getFields()方法,只能获取public属性
1 | |

方法二:使用getDeclaredFields()方法,可以获取所有属性
1 | |

方法三:通过变量名修改属性值
修改public属性值
1 | |
将原来name变量的值改成“yin”,这里要注意用到的还是getField方法,name应为public属性

修改private属性值
1 | |

调用类中的方法
方法一:通过getMethods方法获取
1 | |

方法二:通过方法名获取
调用public方法
1 | |

调用private方法
1 | |
