Open GH1995 opened 4 years ago
JVM为每个加载的class
及interface
创建了对应的Class
实例来保存class
及interface
的所有信息;
获取一个class
对应的Class
实例后,就可以获取该class
的所有信息;
通过Class
实例获取class
信息的方法称为反射(Reflection);
JVM总是动态加载class
,可以在运行期根据条件来控制加载class
。
Java的反射API提供的Field
类封装了字段的所有信息:
通过Class
实例的方法可以获取Field
实例:getField()
,getFields()
,getDeclaredField()
,getDeclaredFields()
;
通过Field
实例可以获取字段信息:getName()
,getType()
,getModifiers()
;
通过Field
实例可以读取或设置某个对象的字段,如果存在访问限制,要首先调用setAccessible(true)
来访问非public
字段。
通过反射读写字段是一种非常规方法,它会破坏对象的封装。
Java的反射API提供的Method
对象封装了方法的所有信息:
通过Class
实例的方法可以获取Method
实例:getMethod()
,getMethods()
,getDeclaredMethod()
,getDeclaredMethods()
;
通过Method
实例可以获取方法信息:getName()
,getReturnType()
,getParameterTypes()
,getModifiers()
;
通过Method
实例可以调用某个对象的方法:Object invoke(Object instance, Object... parameters)
;
通过设置setAccessible(true)
来访问非public
方法;
通过反射调用方法时,仍然遵循多态原则。
Constructor
对象封装了构造方法的所有信息;
通过Class
实例的方法可以获取Constructor
实例:getConstructor()
,getConstructors()
,getDeclaredConstructor()
,getDeclaredConstructors()
;
通过Constructor
实例可以创建一个实例对象:newInstance(Object... parameters)
; 通过设置setAccessible(true)
来访问非public
构造方法。
Java标准库提供了动态代理功能,允许在运行期动态创建一个接口的实例;
动态代理是通过Proxy
创建代理对象,然后将接口方法“代理”给InvocationHandler
完成的。
反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。