1.什么是反射
反射是指在程序运行时,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性。这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
2.反射的作用
- 获取类的名称、package信息、所有属性、方法、注解、类型、类加载器等
- 获取任意对象的属性并且能够改变对象的属性
- 调用对象的方法
- 判断对象所属的类
- 实例化类的对象
- 在应用程序运行时,通过反射可以实现动态代理,动态的调用方法等
3.反射的使用
一个类由三部分组成,构造器 + 属性 +方法
示例代码使用的类
public class Person {
private String name;
private int age;
private String address;
public Person(){}
public Person(String name){
this.name = name;
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
Person(String name, String address){
this.name = name;
this.address = address;
}
... ... //省略get set
public void eat(){
System.out.println("person eat food ...");
}
public void sleep(){
System.out.println("person sleep ...");
}
public String sleep(Integer time){
System.out.println("person sleep " + time + "mins");
return "person sleep " + time + "mins";
}
}
(1)通过反射获取类的构造器
方法说明如下:
| 方法 | 说明 |
|---|---|
| Constructor<?>[] getConstructors() | 获取定义的public的构造器 |
| Constructor getConstructor(Class<?>... parameterTypes) | 根据指定参数类型获取public构造器 |
| Constructor<?>[] getDeclaredConstructors() | 获取定义的所有构造器 |
| Constructor getDeclaredConstructor(Class<?>... parameterTypes) | 根据指定参数类型获取定义的构造器 |
示例代码如下:
//获取所有public的构造器
Constructor<?>[] constructors = personClazz.getConstructors();
//获取指定参数的public构造器
Constructor<?> constructor1 = personClazz.getConstructor(String.class);
//获取所有定义的构造器
Constructor<?>[] declaredConstructors = personClazz.getDeclaredConstructors();
//获取指定参数定义的构造器
Constructor<?> declaredConstructor = personClazz.getDeclaredConstructor(String.class);
(2)通过反射获取类的属性
方法说明如下:
| 方法 | 说明 |
|---|---|
| Field[] getFields() | 获取所有public的属性 |
| Field getField(String name) | 获取指定属性名的public的属性 |
| Field[] getDeclaredFields() | 获取所有的属性 |
| Field getDeclaredField(String name) | 获取指定属性名的属性 |
示例代码如下:
//获取所有public的属性
Field[] fields = personClazz.getFields();
//获取指定属性名的public属性
Field name1 = personClazz.getField("name");
//获取所有定义的属性
Field[] declaredFields = personClazz.getDeclaredFields();
//获取指定属性名的属性
Field name2 = personClazz.getDeclaredField("name");
此外,还可以设置属性的值,示例代码如下:
Constructor<?> constructor = personClazz.getConstructor(String.class);
Object obj = constructor1.newInstance("zys");//实例化一个name为zys的对象
Field nameField = personClazz.getDeclaredField("name");
field.setAccessible(true);//私有属性要设置可访问,否则无权限
nameField.set(zys, "ds");//将对象的obj的name属性重新设置为ds
(3)通过反射获取类的方法
方法说明如下:
| 方法 | 说明 |
|---|---|
| Method[] getMethods() | 获取类的所有public的方法 |
| Method getMethod(String name, Class<?>... parameterTypes) | 获取类的指定参数的public方法 |
| Method[] getDeclaredMethods() | 获取类的所有方法 |
| Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 获取类的指定参数的方法 |
示例代码如下:
//获取类的所有public方法
Method[] methods = personClazz.getMethods();
//根据方法名获取public方法
Method eat = personClazz.getMethod("eat");
//获取类的所有定义的方法
Method[] declaredMethods = personClazz.getDeclaredMethods();
//根据方法名获取方法
Method declaredMethod = personClazz.getDeclaredMethod("test");
此外,获取方法后,可以直接调用,示例代码如下:
Method[] methods = personClazz.getMethods();//获取类的所有public方法
personClazz.getMethod("sleep", Integer.class);//根据方法名获取public方法
Object invoke1 = sleep1.invoke(obj, 10);//直接调用方法
4.反射的原理
主要点就是类的加载时机。正常的应用程序代码,类的加载是程序中的hard code, 而反射是动态地去加载某个类,程序的耦合性较低。反射常见的使用就是动态代理。