反射到底是个啥?
学过初中物理的同学都知道,在日常生活中照镜子时镜子中的世界并非真实的世界,而是通过镜面反射将真实世界映射为一个虚像,可以通过虚像来获取真实事务的某些特征。
同理,在java中反射也是如此。我们通过OOP(面向对象)的三大特征之一的封装性知道,对于一个对象的内部属性或者方法,对于某些私有属性是无法访问的。并且我们项目比较大时可能无法一次就能把程序设计得完美,如果在更新某些功能时如果通过静态编译就需要通过javac编译器把程序重新编译一次,这个过程十分耗时耗力。此时反射横空出世可以完美解决以上问题。反射就是通过实例化对象来获取所属类的信息。
Java的反射机制可以动态获取程序信息和调用对象功能,主要作用体现在程序运行时可以:
- 构造任意一个类的对象
- 获取任意一个对象所属类的信息
- 调用一个类的成员变量或者方法
- 获取一个对象的属性或者方法
反射是如何进行的?
通过程序执行的过程,我们知道通过javac编译器编译后我们得到字节码文件(.class文件),反射针对的主要对象就是这里的字节码文件(.class文件)。反射就是把得到的.class中的各种成分映射为一个个Java对象(成分包括成员变量、方法、属性、构造方法等),具体来说就是通过Class类实例化(注意首字母是大写,与class不同)来得到这个对象,再将这个对象的成分映射为一个个Java对象。
怎么用?
Class实例化对象的方法
Class实例化对象有以下三种方法:
1.通过对象获取:对象名.getclass()
这都new了对象了,再用反射这不是多此一举???所以这种不常用
2.根据类名获得:类名.class
这个还得把Student111这个类导进来,多累啊!!!所以也不常用
3.根据全限定类名获取(最常用):Class.forName("全限定类名“)
这个好!!!输个名字就行
怎么理解Class实例化的过程呢?
可以将Class看成一面镜子,通过实例化得到Class实例化对象就像是镜子照射不同物体得到不同虚像,c1,c2,c3就是三个”虚像“,通过这三个”虚像“来获取本体(student111)的信息。
调用实例化对象获取信息
得到Class类的实例化对象,我们可以调用这个对象获取类的信息
class Student111{
//无参构造器
public Student111(){
}
//有参构造器
public Student111(int age,String name){
this.name =name;
this.age = age;
}
//私有属性
private int age;
//公开属性
public String name;
//公开方法
public void shout(){
System.out.println("你好,我是" + name);
}
//私有方法
private void Old(int age){
this.age =age;
System.out.println("我年龄是:" + age);
}
}
1.获取公开字段信息
获取所有公开字段
public class Hello {
public static void main(String[] args) throws ClassNotFoundException {
Class c3 = Student111.class;
//获取公开字段
Field[] fields = c3.getFields();
for (Field f :fields) {
System.out.println(f);
}
}
}
运行得到:
2.获取所有字段(包括私有和公开)
public class Hello {
public static void main(String[] args) throws ClassNotFoundException {
Class c3 = Student111.class;
//获取所有字段
Field[] fields = c3.getDeclaredFields();
for (Field f :fields) {
System.out.println(f);
}
}
}
3.获取所有公开方法
4.获取所有公开和私有方法
5.调用私有方法
6.调用有参构造器实例化对象并调用私有方法
这里为了方便演示对私有方法修改一下