一、定义
JAVA反射机制是在运行状态中:1)对于任意一个类,都能够知道这个类的所有属性和方法;2)对于任意一个对象,都能够调用它的任意一个方法。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二、提供的功能:
1) 在运行时判断任意一个对象所属的类;
2)在运行时构造任意一个类的对象;
3)在运行时判断任意一个类所具有的成员变量和方法;
4)在运行时调用任意一个对象的方法;
5)生成动态代理。
三、使用的原因
1、扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。
2、在编码阶段不知道那个类名,要在运行期从配置文件读取类名,这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。
四、应用举例
示例中用到的类
class Cat { /* * 用于测试反射机制,省略了参数的getter和setter类 */ private String name; private int age; private String sex; public String hostname;//主人名字 public static String info="猫是一种XX的动物……";//动物说明 public Cat(){ this.name="defaultname"; this.age=0; this.sex="defaultSex"; this.hostname="Lucy"; } public Cat(String name,Integer age,String sex) { this.name=name; this.age=age; this.sex=sex; this.hostname="Kate"; } public static void showCatInfo(String time){ System.out.println("Cat.showCatInfo():"+info); } public void feed(String host){ System.out.println("Cat.feed()"+host); } }
1、获取某个对象的属性
public Object getProperty(Object owner,String fieldName) throws Exception { Class ownerClass=owner.getClass();//通过已知对象获取其Class对象 Field field=ownerClass.getField(fieldName);//通过Class对象获取声明的属性 Object property=field.get(owner);//通过对象获取属性的实例,如果该属性是私有的会异常 return property; }
使用如下代码测试该方法:
public static void main(String[] args) { // TODO Auto-generated method stub Reflector rf=new Reflector(); Cat cat=new Cat(); try { Object object=rf.getProperty(cat, "hostname"); if(object!=null){ System.out.println("Reflector.main()"+object.toString()); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出:Reflector.main()Lucy
2、获取某个类的静态属性
public Object getStaticProperty(String className,String fieldName) throws Exception { Class ownerClass=Class.forName(className);//获取已知对象的Class对象 Field field=ownerClass.getField(fieldName);//通过Class对象获取声明的属性 Object property=field.get(ownerClass);//因为该属性是静态属性,应该从类Class里直接获取,此处是ownerClass return property; }
测试代码:
public static void main(String[] args) { // TODO Auto-generated method stub Reflector rf=new Reflector(); try { Object object=rf.getStaticProperty("com.Cat", "info"); if(object!=null){ System.out.println("Reflector.main()"+object.toString()); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出:Reflector.main()猫是一种XX的动物……
3、执行某对象的方法
public Object invokeMethod(Object owner,String methodName,Object args[]) throws Exception{ Class ownerClass=owner.getClass();//获取已知对象的Class对象 Class[] argClasses=new Class[args.length];//获取参数对象的Class for(int i=0;i<args.length;++i){ argClasses[i]=args[i].getClass(); } Method method=ownerClass.getMethod(methodName, argClasses);//通过方法名和参数对象的Class获取方法对象 return method.invoke(owner, args);//通过执行这个方法的对象和参数对象数组执行这个方法,返回值是Object,也既是该方法的返回值。 }
测试代码:
public static void main(String[] args) { // TODO Auto-generated method stub Reflector rf=new Reflector(); Cat cat=new Cat();//执行方法的对象 Object arg[]={(Object)new String("Mary")};//方法的参数对象数组 try { rf.invokeMethod(cat, "feed",arg); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出:Cat.feed()Mary
4、执行某个类的静态方法
public Object invokeStaticMethod(String className,String methodName,Object args[]) throws Exception{ Class ownerClass=Class.forName(className);//获取已知对象的Class对象 Class[] argClasses=new Class[args.length];//获取参数对象的Class for(int i=0;i<args.length;++i){ argClasses[i]=args[i].getClass(); } Method method=ownerClass.getMethod(methodName, argClasses);//通过方法名和参数对象的Class获取方法对象 return method.invoke(null, args);//通过执行这个方法的对象和参数对象数组执行这个方法,返回值是Object,也既是该方法的返回值。 }
测试代码:
public static void main(String[] args) { // TODO Auto-generated method stub Reflector rf=new Reflector(); Object arg[]={(Object)new String("Mary")};//方法的参数对象数组 try { rf.invokeStaticMethod("com.Cat", "showCatInfo",arg); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
//PS:基本的原理和例3相同,不同点是最后一行,invoke的一个参数是null,因为这是静态方法,不需要借助实例运行。
输出:Cat.showCatInfo():猫是一种XX的动物……
5、新建实例
/* * 新建实例 * 这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。 */ public Object newInstance(String className,Object args[])throws Exception{ Class ownerClass=Class.forName(className);//获取已知对象的Class对象 Class[] argClasses=new Class[args.length];//获取参数对象的Class for(int i=0;i<args.length;++i){ argClasses[i]=args[i].getClass(); } Constructor constructor=ownerClass.getConstructor(argClasses);//获取这个类的构造器 return constructor.newInstance(args);//新建实例 }
测试代码:
public static void main(String[] args) { // TODO Auto-generated method stub Reflector rf=new Reflector(); Object arg[]=new Object[3];//方法的参数对象数组 arg[0]=new String("CatName1"); arg[1]=new Integer(3); arg[2]=new String("Male"); try { Cat cat=(Cat)rf.newInstance("com.Cat",arg); System.out.println("Cat name is "+cat.getName()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出:Cat name is CatName1