1.什么是反射
反射就是动态的加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都可以知道这个类的任意方法和属性;对于一个对象,可以调用这个对象的任意方法和属性。这种动态的获取信息以及调用对象方法的功能称之为java的反射机制。
2.反射的优缺点
2.1优点
反射提高了程序的灵活性和扩展性,在底层框架中用的比较多,比如Spring等。但是,在平常业务开发的层面用的比较少,还是少用吧。
2.2缺点
反射性能不那么好,耗时。
假如我们进行如下操作:创建一个对象的实例,然后赋值并取值。通过常规的new对象,set设置值,get取值的办法,整个过程耗时会很短。与之相比,通过反射的方法拿到实例,在进行赋值取值的操作,会更耗时,性能要差不少。
3.反射的实现
具体说明都会写在代码的注释里,这里就不再说什么了。
3.1获取Class对象的三种方法
首先创建一个实体类Person,定义一些基本的属性和方法,代码略。
然后是获取Person的Class对象的三种方法:
public class FanShe {
public static void main(String[] args) throws ClassNotFoundException {
//1.通过Class对象的forName(全类名)静态方法获取;全类名=包名.类名
Class<Person> clazz = (Class<Person>) Class.forName("Person");
//2.通过类名.class获取
Class<Person> clazz2 = Person.class;
//3.通过对象的getClass()方法获取
Person person = new Person();
Class<Person> clazz3 = (Class<Person>) person.getClass();
}
}
3.2通过Class对象获取成员变量、构造方法、成员方法
简要说明:
get方法特点:带s的方法表示获取获取多个成员/构造,不带s的方法表示获取指定某个成员/构造;带Declared的方法表示获取任意类型的成员/构造,不带Declared的方法表示获取public修饰的成员/构造。
3.2.1. 获取成员变量
clazz.getFields() -> 获取所有public修饰的成员变量
clazz.getField(String name) -> 获取一个指定名称的 public修饰的成员变量
clazz.getDeclaredFields() -> 获取所有的任意修饰符类型成员变量
clazz.getDeclaredField(String name) -> 获取任意修饰符类型指定名称的成员变量
Field field = clazz.getField("age"); //获取一个指定名称的public修饰的成员变量
Field[] fields = clazz.getFields(); //获取所有public修饰的成员变量
Field field1 = clazz.getDeclaredField("name"); //获取一个指定名称的任意成员变量
Field[] fields1 = clazz.getDeclaredFields(); //获取所有的任意修饰符修饰的成员变量
3.2.2.获取构造方法
clazz.getConstructors() -> 获取所有public修饰的构造方法
clazz.getConstructor(Class<?>… parameterTypes) -> 获取指定参数类型的public类型的构造
clazz. getDeclaredConstructor(Class<?>… parameterTypes) -> 获取指定参数类型的任意类型的构造
clazz.getDeclaredConstructors() -> 获取任意类型所有的构造方法
代码和上面类似,就不再重写了。
3.2.3 获取成员方法
clazz.getMethods() -> 获取所有public修饰的方法(可以获取父类的public修饰的方法)
clazz.getMethod(String name, Class<?>… parameterTypes) -> 获取一个指定名称指定参数类型的public类型成员方法
clazz.getDeclaredMethods() -> 获取任意类型所有的成员方法
clazz.getDeclaredMethod(String Class, 类<?>… parameterTypes) -> 获取一个指定名称指定参数类型的任意类型成员方法
代码:同上
3.3操作成员变量、构造方法、成员方法
3.3.1 操作成员变量:获取值以及设置值
field.get(Object obj); -> 表示获取哪个对象的field成员变量值;
field.set(Object obj, Object value); -> 表示设置obj对象的field成员变量值为value;
注意:如果成员变量是非public修饰的,那么必须要在get和set之前取消访问检查:field.setAccessible(true);
field1.setAccessible(true); //取消检查
Person person1 = clazz.newInstance(); //获取实例
field1.set(person1, "小明"); //设置属性值
System.out.println(field1.get(person1)); //获取属性值
3.3.2 操作构造方法:创建对象
Object obj=constructor.newInstance(Object…param); -> 创建对象,并且传递构造需要的参数
Object obj=Class对象.newInstance(); -> 执行的是空参构造
注意:如果构造方法是非public修饰的,那么必须要在newInstance之前取消访问:constructor.setAccessible(true);
3.3.3. 操作成员方法:调用方法
method.invoke(Object obj, Object… args); -> 执行obj对象身上的method方法并给方法传递的参数值为args。
Method method = clazz.getMethod("get");
method.invoke(person1); //get方法没有参数 ,所以参数部分不用填或者写null都可以
注意:如果成员方法是非public修饰的,那么必须要在invoke之前取消访问检查:method.setAccessible(true);