反射
- 各种配置文件其实就是一些参数信息
class Class{
//...
}
- Class类:大写开头的Class类将java中的.class字节码文件也给看成了一个类
想要对一个类进行解剖,只要获取到该类的字节码文件对象即可
1. 获取字节码文件对应对象3种方法
- Object 类中的getClass()方法
比如p1和p2是同一个类的两个不同的实例,二者的getClass()方法返回的是同一个类
缺点:得需要new对象 - 任何数据类型都具备一个静态属性.class来获取其对应的Class对象
比如Person.class
缺点:简单,但是还得明确用到类中的静态成员
想法:给我名字就行,我来返回对应的Class对象,上述两种均不行
- 使用Class的forName方法
找不到就报错ClassNotFoundException
提供名字后,会到classpath路径下面找
注意要加全包名!
2. 与之前new有什么区别
- 早先的方法
package.Person p=new package.Person()
执行过程:
- 在classpath下找到package.Person类的字节码文件
- 将这个字节码文件加载进内存,创建这个字节码文件对象
- 之后创建Person对象
其实就是Class对象中装载着描述这个对象的信息,只能由jvm创建
- 现在的方法
手里只有一个字符串
String name="package.Person";
Class clazz=Class.forName(name);
Object obj=clazz.newInstance();//会自动初始化Person
//一般被反射的类都带有空参,否则就需要进行获取构造函数
3. 获取构造函数
getConstructor
String name="package.Person";
Class clazz=Class.forName(name);
//接下来获取到指定的构造函数对象
Constructor constructor=clazz.getConstructor(String.class,int.class);
Object obj=constructor.newInstance("xiaoming".38);
4. 获取字段
Class clazz=Class.forName("package.Person");
Field field=clazz.getField("age");//如果age是私有那么报错
Field field2=clazz.getDeclareField("age");//只获取子类,但是包含私有
//然后我想设置值,或者获取值(本来我是不知道这个类中的值的,因为这个类是别人写的)
Object obj=clazz.newInstance();//注意了,此时的类的类名我们只有一个字符串!
//所以只能是使用Object向上转型,其实就是用具体的类名获取内部值当然好,但是这样扩展性在哪,毕竟代码只写一遍,也就是说我上面所写的全部代码是针对任何类名的类的
field.setAccessible(true);//可以暴力访问(不建议)
Object o=field.get(obj);//这样是访问变量
field.set(obj,89);//这样是设置变量(私有无效)
5. 获取指定class中的公共函数
方法数组
Class clazz=Class.forName("package.Person");
Method[] methods=clazz.getMethods();//获取所有共有方法,包括父类
methods=clazz.getDeclaredMethods();//获取所有方法,仅限于本类,包含私有方法
无参数
Class clazz=Class.forName("package.Person");
Method method=clazz.getMethod("show",null);//获取空参数一般方法
Object obj=clazz.newInstance();
method.invoke(obj,null);
有参数
Class clazz=Class.forName("package.Person");
Method method=clazz.getMethod("paramMethod",String.class,int.class);//获取带参数一般方法
Object obj=clazz.newInstance();
method.invoke(obj,"xiaoqiang",89);