Java反射整理

来源:互联网 发布:radio标签js取值 编辑:程序博客网 时间:2024/06/06 09:07


Java反射整理

摘要:         无论是在C#还是Java(平常常玩儿的就这俩,所以这么举例,别的语言也雷同!),为了获取类的灵活性,我们会时常使用反射,将类的信息写入配置,通过运行时候动态获取类,类的方法,字段,等等。


    

   无论是在C#还是Java(平常常玩儿的就这俩,所以这么举例,别的语言也雷同!),为了获取类的灵活性,我们会时常使用反射,将类的信息写入配置,通过运行时候动态获取类,类的方法,字段,等等。


     在Java中,我们通常是一个思路来动态访问类信息的,先获取类的Class 类,这个Class指明了是哪个类,然后通过获取到的Class get各种类信息。


一,获取Class类


     
public class ClassDemo1 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException{//Foo的实例对象如何表示Foo foo1=new Foo();//foo1就表示出来了//Foo这个类 也是一个实例对象,Class类的实例对象如何表示//任何一个类都是Class类的实例对象,这个实例对象有3中表示方式/*第一种表示方式--》实际在告诉我们任何一个类都有一个隐含的静态成员变量*/Class c1=Foo.class;/*第二种表达方式:已知该类的对象,通过getClass方法*/Class c2=foo1.getClass();/*官网:c1/c2表示了Foo类的类类型(class type) * 类也是对象,是class类的实例对象 * 这个对象我们成为该类的类类型 * *//*不管c1 or c2都代表了Foo类的类类型,一个类只可能是Class类的一个对象*/System.out.println(c1==c2);//true//第三种表达方式Class c3=null;c3=Class.forName("ShuiTian.NaiLuo.Reflect.Foo");System.out.println(c3);/*我们完全可以通过类的类类型创建该类的对象 * 通过c1 or c2 or c3创建父的实例 *  * */Foo foo=(Foo)c1.newInstance();//使用newInstance需要有无参数的构造方法}}class Foo{}


       主要有上面三种方式:第一种通过类的静态变量获取;第二种通过实例的getClass方法获取,第三种通过一个字符串来动态加载;仔细观察这三种方式,感觉最后一种用的还是比较多的,比如为数据库加载驱动的时候,配置Spring的时候,这种方式使得类的装配更具有灵活性。例如,我们可以使用这种方式在运行时候动态加载类:

   
public class DynamicLoadClass {public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException{String animalName="Cat";Animal animal = null;switch (animalName){case "Cat":animal=(Animal)Class.forName("ShuiTian.NaiLuo.Reflect.Cat").newInstance();break;case "Dog":animal=(Animal)Class.forName("ShuiTian.NaiLuo.Reflect.Dog").newInstance();break;}System.out.println(animal);System.out.println(animal.getClass().getSimpleName());}}interface Animal{}class Cat implements Animal{}class Dog implements Animal{}

 

 二,获取类信息


             当我们使用各种方法获取到类class之后,就可以使用这个class访问类的信息了。

       1,获取类的方法信息


                      
/* * 打印类的信息,包括类的成员函数,类的成员变量 参数是一个对象,该对象的所属信息 */public static void printClassMethodMessage(Object obj) {// 要获取类的信息,首先要获取类的类类型 class typeClass c = obj.getClass();// 传递的是哪个子类的对象// 获取类的名称System.out.println(c.getName());/* * Method类是方法对象 一个成员方法就是一个Method对象 getMethods获取的是所有的public函数,包括从父类继承而来的 * c.getDeclaredMethods()获取的是所有该类声明的方法,不问访问权限 */Method[] ms = c.getMethods();  //获取类的方法数组for (Method method : ms) { //对类的方法数组进行循环,在循环中获取函数返回值信息及参数信息,也可以对方法进行动态调用// 得到方法的返回值类型的类类型Class returnType = method.getReturnType();System.out.print(returnType.getName() + "(");// 得到方法的名称System.out.print(method.getName());// 获取方法的参数类型--->得到的是参数列表的类型的类类型Class[] paramTypes = method.getParameterTypes();for (Class c1 : paramTypes) {System.out.print(c1.getName() + ",");}System.out.println(")");}printFieldMessage(obj);}


       2,获取类的成员变量的信息


                  
/*获取类的field信息*/public static void printFieldMessage(Object obj) {Class c=obj.getClass();/* * 成员变量也是对象 java.lang.reflect.field Field类封装了关于成员变量的操作 * getFields方法获取的是所有public成员变量的信息 getDeclaredFields获取的是该类自己声明的成员 */Field[] fs = c.getDeclaredFields();for (Field field : fs) {/* 得到成员变量的类类类型 */Class fieldType = field.getType();String typeName = fieldType.getName();/* 得到成员变量的名称 */String fieldName = field.getName();System.out.println(fieldType + "," + fieldName);}}

        

      3,获取对象的构造函数的信息


              
/*打印对象的构造函数的信息*/public static void printConMessage(Object obj){Class c=obj.getClass();/* * java.lang.constructors封装了构造函数的信息 * getConstructors()获取了所有的public的构造函数的信息 * getDeclaredConstructors:得到了自己声明的构造函数 * */Constructor[] cs =c.getDeclaredConstructors(); //获取构造函数数组for(Constructor con :cs ){  //分别对各个构造函数进行遍历System.out.print(con.getName()+"(");//获取构造函数的参数列表----得到的是参数列表的类类型Class[] paramTypes=con.getParameterTypes();  //得到构造函数的参数列表for(Class param:paramTypes){System.out.print(param.getName()+",");}System.out.println(")");}}


      4,通过反射动态调用方法

             
/* * 测试方法的反射 *  * */public class MethodDemo1 {public static void main(String[] args) throws InstantiationException,IllegalAccessException, ClassNotFoundException,NoSuchMethodException, SecurityException, IllegalArgumentException,InvocationTargetException {// 获取print(int,int)方法Class a = Class.forName("ShuiTian.NaiLuo.Reflect.A");/* * 获取方法名称,参数列表。。。 getMethod:获取的是public的方法 getDeclaredMethod:获得的是自己声明的方法 */Method m = a.getMethod("print", new Class[] { int.class, int.class });/* * 方法的反射操作 使用m对象来进行方法的调用 方法返回值问题 1,无返回值返回null 2,有返回值,返回具体值 */m.invoke(a.newInstance(), 10, 10);// m.invoke(a,10,10);System.out.println("==========分割线============");Method m2 = a.getMethod("print", String.class, String.class);m2.invoke(a.newInstance(), "lhc", "水田");}}class A {public void print(int a, int b) {System.out.println(a + b);}public void print(String a, String b) {System.out.println(a.toUpperCase() + "," + b.toLowerCase());}}






            额,有了这个基础,再去看spring的源码,估计就差不多能看懂了。