Object result = method.invoke(bean);
反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。
程序中对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性。但在有的时候并没有进行编译期就要直接使用,比如class.forName方法。
反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道对象的类型。
Java反射框架主要提供以下功能:
1.在运行时动态进行类加载;
2.在运行时创建一个对象;
3.在运行时获取类(对象)的任意成员变量和方法
4.在运行时调用任意一个对象的方法(通过反射甚至可以调用private方法);
重点是运行时而不是编译时
当我们在使用IDE(如Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点号,编译器就会自动列出它的属性或方法,这里就会用到反射。
反射最重要的用途就是开发各种通用框架。
很多框架(比如Spring)都是配置化的(比如通过XML文件配置JavaBean,Action之类的),为了保证框架的通用性,它们可能需要根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象。
<action name="login" class="org.ScZyhSoft.test.action.SimpleLoginAction" method="execute">
<result>index.jsp</result>
<result name="error">login.jsp</result>
</action>
配置文件与Action建立了一种映射关系,当View层发出请求时,请求会被StrutsPrepareAndExecuteFilter拦截,然后StrutsPrepareAndExecuteFilter会去动态地创建Action实例。
struts与spring mvc的区别是struts是原型的,springmvc是单列的。
获得Class对象的三种方法:
(1)使用Class类的forName静态方法
(2)直接获取某一个对象的class,比如 a.class
(3)调用某个对象的getClass()方法,比如 a.getClass()
instanceof 和 isInstance区别:
obj instanceof Type
class.isInstance(obj)
System.out.println("ok" instanceof String);
System.out.println("ok".getClass().isInstance(""));
通过反射来生成对象主要有两种方式:
(1)使用Class对象的newInstance()方法来创建Class对象对应类的实例
(2)先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例:
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);
获取某个Class对象的方法集合,主要有以下几个方法:
getDeclaredMethods()方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
public Method[] getDeclaredMethods() throws SecurityException
getMethods()方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。
public Method[] getMethods() throws SecurityException
getMethod方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象
public Method getMethod(String name, Class<?>... parameterTypes)
获取类的成员变量(字段)信息,直接使用较少,因为变量一般为私有的。
getFiled: 访问公有的成员变量
getDeclaredField:所有已声明的成员变量。但不能得到其父类的成员变量
getFileds和getDeclaredFields用法同上(参照Method)
当我们从类中获取了一个方法后,我们就可以用invoke()方法来调用这个方法。invoke方法的原型为:
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。