反射
1、是java API,是java提供的现成的类!--接受API提供的功能!
2、是java提供的动态执行机制,动态加载类,动态创建对象,动态访问属性,动态调用方法。
静态与动态
静态:事先约定的规则,执行期间按照固定规则执行。
动态:事先没有约定,在执行期间动态确定执行规则。
java中的静态执行:编译以后就确定了执行规则(执行次序),在运行期间按照编译结果顺序执行。
Foo foo=new Foo();
foo.hello();
java中的动态执行:运行期间才能确定加载哪些类,创建哪些对象,执行哪些方法。。。。
业务需求:执行某个类中全部的以test为开头的无参无返回值的非静态方法。
动态加载类:
java提供了动态加载类的API
Class cls=Class.forName(类名);
如:
Class cls=Class.forName(“demo.Foo”);
动态创建对象:
语法:cls.newInstance();
执行cls引用的类信息中的无参构造器,动态创建实例,如果类没有无参数构造器,则抛出异常!
提示:反射可以调用有参构造器。
案例:
Scanner in=new Scanner(System.in);
System.out.println("输入类名:");
String className=in.nextLine();
//动态加载类
Classcls=Class.forName(className);
System.out.println(cls);
//动态创建对象
Object obj=cls.newInstance();
System.out.println(obj);
动态获取类的方法信息:
动态执行方法:
invoke:调用
语法:
method.invoke(执行方法的对象,传递的参数)
必须在对象上执行一个非静态方法,调用方法时必须有对象。
在invoke方法执行的时候,必须传递包含当前方法的对象!!!
//动态加载类
Scanner in=new Scanner(System.in);
System.out.println("输入类");
//动态获取全部方法信息
Method[] arr=cls.getDeclaredMethods();
for(Method method:arr){
System.out.println(method);
System.out.println(method.getName());
System.out.println(method.getReturnType());
//动态创建对象
Object obj=cls.newInstance();
//迭代全部方法查找以test为开头的方法
if(method.getName().startsWith("test")){
System.out.println(method+"找到了");
//动态执行方法
method.invoke(obj);
}
}
使用invoke
Object obj=method.invoke(对象,参数1,参数2…)
invoke 方法有返回值,返回被调用方法执行的结果,对象后面参数是执行方法时候传递的参数
invoke可以调用私有方法。
Scanner in=new Scanner(System.in);
System.out.println("请输入类名");
//1、找到demo方法
//Class提供了根据方法签名找到指定方法信息的API
String name="demo";//方法签名
//类型列表 Class[]
//String.class 表示字符串的类型
//int.class 表示int类型
//任何.class 表示任何的类型
Class[] types={String.class,int.class};
//根据方法的签名在cls查找方法信息
Method method=cls.getDeclaredMethod(name,types);
//找到了私有方法。
System.out.println(method);
//执行私有方法
//打开方法的执行权限!!!违反封装
method.setAccessible(true);
Object value=method.invoke(obj, "Tom",12);
System.out.println(value);
反射用途
1、 eclipse中解析类的结构使用了反射
2、Junit识别被测试方法使用了反射
- JUnit3利用反射查找test开头的方法
- JUnit4利用反射解析@Test查找测试方法
3、Spring管理Bean对象,注入Bean属性使用了反射
- 利用反射创建了Bean对象实例
- 利用反射注入Bean的属性
4、注解的解析使用了反射
- 利用反射API支持注解