1.还是先说定义, 什么叫发射, 反射是什么.
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
以上是百度的结果, 各种看不懂, 没关系, 我个人对反射的理解是通过一种途径来获取一个类的信息, 包括变量, 方法等相关内容, 然后可以来对这些信息进行操作, 譬如赋值, 或者调用方法.
2.为什么要使用反射机制:
在java中, 当你想要new一个东西的时候, 这个东西必须已经实现你才能new, 那如果在你new的时候, 这个东西还没有实现, 那怎么办呢?
以下就是假设的反射使用场景
1)当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢?
因为程序是支持插件的(第三方的),在开发的时候并不知道 。所以,无法在代码中 New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。
反射的目的就是为了扩展未知的应用。很多工厂模式就是使用的反射。
2)在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码
new ClassName(),而必须用到反射才能创建这个对象.
3.反射的具体实现.
1.Class类:
获取一个Class类有三种方法:
//第一种获取方法,直接了当
Class clazz1 = String.class;
//第二种获取方法,对实体类运用方法
String str = "just do it";
Class clazz2 = str.getClass();
//第三种获取方法,直接传递一个类名,字符串形式
Class clazz3 = Class.forName("java.lang.String");
2.Field类:
获取一个Filed(变量)类:
//1-->获取所有声明的变量
Field[] fields1 = clazz1.getDeclaredFields();
//2-->获取所有的公共类变量
Field[] fields2 = clazz1.getFields();
//3-->获取指定变量名(所有声明的变量都可获取)
Field field1 = clazz1.getDeclaredField("value");
3.Method类:
Method[] methods1 = clazz1.getDeclaredMethods();
Method[] methods2 = clazz1.getMethods();
Method method1 = clazz1.getDeclaredMethod("checkBounds",new Class[]{byte[].class,int.class,int.class});
Method method2 = clazz2.getMethod("hashCode");
如果方法中的无参数,则得到方法时,只需传一个方法名即可
4.Constructor类:
Constructor[] cons1 = clazz1.getDeclaredConstructors();
Constructor[] cons2 = clazz1.getConstructors();
Constructor con1 = clazz1.getConstructor(char[].class);
Constructor con2 = clazz1.getDeclaredConstructor(new Class[]{int.class,int.class,char[].class});
5.由一个class得到一个类的实体
String obj = (String) clazz1.newInstance();
用此种方法,类必须有默认构造函数
6.由一个Constructor对象,得到类的实体
String str2 = (String) con1.newInstance(new char[]{'j','u','s','t'});
7.字段类修改获取字段数据
public Object get(Object obj);//获取一个字段上的数据
public void set(Object obj,Object value);//设置一个字段上的数据
8.method方法执行:
//public Object invoke(Object obj,Object... args)//方法执行
String testStr = "testStr";
Method method = String.class.getMethod("charAt", new Class[]{int.class});
char ch = (char) method.invoke(testStr, 1);
还有一种特殊的反射是针对Bean的操作, 叫做内省.
一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。