认识反射和Class类 + 访问对象的字段 + 调用对象的方法 + 调用构造函数 + 获取继承关系 + 动态代理
认识反射和Class类
反射(Reflection),Java的反射是指程序在运行期可以拿到一个对象的所有信息。
JVM为每个加载的 class
及 interface
创建了对应的 Class
实例来保存 class
及 interface
的所有信息;这里的 Class
类型是一个名叫 Class
的 class
。
获取一个 class
对应的 Class
实例后,就可以获取该 class
的所有信息;
通过 Class
实例获取 class
信息的方法称为反射(Reflection);
JVM总是动态加载class,可以在运行期根据条件来控制加载class。
访问对象的字段
Java的反射API提供的Field类封装了字段的所有信息:
通过Class实例的方法可以获取Field实例:
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
通过Field实例可以获取字段信息:
- getName():返回字段名称,例如,”name”;
- getType():返回字段类型,也是一个Class实例,例如,String.class;
- getModifiers():返回字段的修饰符,它是一个int,不同的bit表示不同的含义。
1 | import java.lang.reflect.Field; |
运行结果
1 | public int Student.score |
通过Field实例可以读取或设置某个对象的字段,如果存在访问限制,要首先调用setAccessible(true)来访问非public字段。
通过反射读写字段是一种非常规方法,它会破坏对象的封装。因此多用于底层设计。
调用对象的方法
java的反射API提供的 Method
对象封装了方法的所有信息:
通过 Class
实例的方法可以获取 Method
实例:
- Method getMethod(name, Class…):获取某个public的Method(包括父类)
- Method getDeclaredMethod(name, Class…):获取当前类的某个Method(不包括父类)
- Method[] getMethods():获取所有public的Method(包括父类)
- Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
通过 Method
实例可以获取方法信息:
- getName():返回方法名称,例如:”getScore”;
- getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
- getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
- getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
通过 Method
实例可以调用某个对象的方法:Object invoke(Object instance, Object... parameters);
通过设置 setAccessible(true)
来访问非public方法;
通过反射调用方法时,仍然遵循多态原则。
调用构造函数
通过Class实例获取Constructor的方法如下:
- getConstructor(Class…):获取某个public的Constructor;
- getDeclaredConstructor(Class…):获取某个Constructor;
- getConstructors():获取所有public的Constructor;
- getDeclaredConstructors():获取所有Constructor。
1 | public class Main { |
获取继承关系
通过Class对象可以获取继承关系:
- Class getSuperclass():获取父类类型;
- Class[] getInterfaces():获取当前类实现的所有接口。
通过Class对象的isAssignableFrom()方法可以判断一个向上转型是否可以实现。
动态代理
Java标准库提供了动态代理功能,允许在运行期动态创建一个接口的实例;
动态代理是通过Proxy创建代理对象,然后将接口方法“代理”给InvocationHandler完成的。