反射获取类的结构信息

来源:互联网 发布:社会主义生产方式知乎 编辑:程序博客网 时间:2024/06/01 20:02

可以通过某个类的类类型获取该类的信息。比如该类中的方法、成员变量、构造方法等信息。即通过反射得到类的完整结构。

java.lang.reflect包中的重要几个类

  • Method:表示类中的方法。
  • File:表示类中的属性。
  • Constructor:表示类中的构造方法。

预备知识

万事万物皆对象。既然写的类是对象,那么基本数据类型是不是对象。答案是肯定的


 1 public class ClassDemo01 { 2     public static void main(String[] args) { 3         Class c1=double.class; 4         Class c2=Double.class; 5         Class c3=void.class; 6         System.out.println("double.class:"+c1.getName()); 7         System.out.println("Double.class:"+c2.getName()); 8         System.out.println("Double.class的简称:"+c2.getSimpleName()); 9         System.out.println("void.class:"+c3.getName());10     }11 }

运行结果:

double.class:doubleDouble.class:java.lang.DoubleDouble.class的简称:Doublevoid.class:void

说明

 1、基本数据类型、void等关键字都是Class类的实例

 2、double.class与Double.class表示的是不同的概念:
——double.class表示的是基本数据类型的类类型。
——Double.class表示的是Double类的类类型。Double是double的封装类。

3、getName、getSimpleName方法:

——getName以 String 的形式返回此Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。返回的是具体的包名.类名

——getSimpleName返回的是不带包名的类名

Double.class表示的是Double类的类类型。在java中我们每写的一个类编译后字节码文件都是类名.class的形式。因此这里也可以将Double.class理解为Double类的字节码文件。


强调:基本数据类型是Class类型的,是Class类的实例对象。


主要注意基本数据类型是Class类对象,是Class类型的数据。下面我们会用到,我们方法的返回值类型,参数类型都是Class类的实例

Class类的基本API

要获取类中的方法、成员变量、构造函数,就要先获取该类的类类型。换种方式理解——我们想要获取的是类中的信息,即Class中的信息,是不是理所应当的需要获取Class的实例对象后才可以操作。

获取类中的方法

 1 publicclass ClassUtil { 2  3     /**获取类中的方法 4      * @param obj 类的实例 5      */ 6     public static void printMethod(Object obj){ 7             //首先获取该类的类类型 8             Class c1=obj.getClass(); 9            //获取类中方法数组  数组中每个数据都是Method对象10             Method ms[]=c1.getMethods();//获取本类,父类,超类中所有public方法11             for(Method m:ms){12                            //类中返回值类型13                    Class returnType=m.getReturnType();14                           //返回值类型的名称15                    System.out.print("方法:"+returnType.getName()+" ");16                            //方法名称17                      System.out.print(m.getName()+"(");18                             //类中参数19                      Class parameTypes[]=m.getParameterTypes();20                       for(Class parameType:parameTypes){21                                 System.out.print(parameType.getName()+",");22                       }23                         System.out.println(")");24            }25      }26 }

说明:既然万事万物皆对象,理所当然方法也是对象。方法Method是——java.lang.reflect.Method类的对象。

  1. 通过class.getMethods()方法获取所有的方法,返回Method类型的数组。
  2. 方法是由返回值类型、方法名、参数组成。所以Method类里面拥有获取它们的方法。
  3. 返回值类型、参数都是Class类型的,所以返回值类型也是Class或Class类型数组。

getMethods()、getDeclaredMethods()区别

——getMethods():获取本类、父类、超类中所有public方法

——getDeclaredMethods():获取本类中所有方法,包括private、public等。

获取某类的成员变量

 1     /**获取类中所有成员变量 2      * @param obj  类的实例化对象 3      */ 4     public static void printField(Object obj){ 5         //首先获取类类型 6         Class c1=obj.getClass(); 7         //成员变量也是对象  Field类的对象 8         Field fs[]=c1.getDeclaredFields(); 9         for(Field f:fs){10             //变量的类型11             Class fieldType=f.getType();12             System.out.print("成员变量"+fieldType.getName()+" ");13             System.out.println(f.getName());14         }15     }

说明

 成员变量也是对象,是java.lang.reflect.Field类的对象

——getFields():获取所有public类型的成员变量。

——getDeclaredFields():获取本类中所有成员变量。

 

获取构造方法

 

 1     public static void printConstructor(Object obj){ 2         Class c1=obj.getClass(); 3         Constructor cs[]=c1.getDeclaredConstructors(); 4         for(Constructor c:cs){ 5             System.out.print("构造函数:"+c.getName()+"("); 6             //参数类型 7             Class parameTypes[]=c.getParameterTypes(); 8             for(Class parameType:parameTypes){ 9                 System.out.print(parameType.getName()+",");10             }11             System.out.println(")");12         }13     }

说明:构造函数是java.lang.reflect.Constructor类的对象

测试代码:很简单的

        ClassUtil.printMethod("");
        ClassUtil.printField(new Integer(1));
        ClassUtil.printConstructor("");

取得类的结构——进一步理解

 
interface China{         public static final String NATIONAL="China";         public void sayChina();         public String sayHello(String name,int age);}class Person implements China{        private String name;        private int age;        // 构造函数        public Person() {            super();        }        public Person(String name) {             super();            this.name = name;       }       public Person(String name, int age) {            super();            this.name = name;            this.age = age;       }       // set与get方法       public String getName() {            return name;       }       public void setName(String name) {             this.name = name;       }       public int getAge() {             return age;       }       public void setAge(int age) {             this.age = age;       }       // 继承方法       @Override       public void sayChina() {        }        @Override        public String sayHello(String name, int age) {               return null;        }}

1、取得全部实现接口

Class infas[]=c1.getInterfaces();for(Class infa:infas){System.out.println("实现的接口名称:"+infa.getName());}

2、取得父类

       Class superClass=c1.getSuperclass();       System.out.println("继承的父类:"+superClass);

说明:因为一个类可以实现多个接口,但是只能继承一个父类,所以要是获取的父类是单值,获得的实现接口是数组类型。

运行结果:

实现的接口名称:com.xj.China继承的父类:class java.lang.Object
注意:如果一个类没有明确的指明继承的类,那么默认就继承Object类。否则就是继承指定的那个类。

3、取得全部的构造方法

  • 直接输出Constructor对象得到的信息

Constructor constructors_auto[]=c1.getConstructors();for(Constructor constructor:constructors_auto){        System.out.println("全部的构造方法——直接输出:"+constructor);}


  • 手工拼凑 构造方法的组成是由 访问权限 方法名称(参数类型)组成的。

Constructor constructors_hand[]=c1.getConstructors();for(Constructor constructor:constructors_hand){         System.out.print("全部构造方法——手动设置:");              //访问权限         System.out.print(Modifier.toString(constructor.getModifiers())+" ");              //方法名称         System.out.print(constructor.getName()+"(");              //构造方法中的参数         Class parameterTypes[]=constructor.getParameterTypes();//参数类型         for(int i=0;i<parameterTypes.length;i++){               System.out.print(parameterTypes[i].getName()+" arg"+i);               if(i<parameterTypes.length-1){                      System.out.print(",");               }         }         System.out.println(")");}

Constructor类的对象,所以这里面采用Constructor类型的数组来接收类中的构造函数。

说明:采用了两种方式打印出类中的全部构造方法。分别是:

——直接输出Constructor对象,得到完整的构造函数信息

——自己手工的拼凑出信息。根据构造函数由修饰符(访问权限)、构造方法的名称、参数类型组成。来拼凑出构造方法。

注意

1、getModifiers():可以获取构造方法的修饰符。此方法返回的是int类型,需要使用Modifier类中静态方法toString()将int类型转为对应的修饰符。修饰符对应的整型如下:

java.lang.reflect.Modifierpublic static final intABSTRACT1024public static final intFINAL16public static final intINTERFACE512public static final intNATIVE256public static final intPRIVATE2public static final intPROTECTED4public static final intPUBLIC1public static final intSTATIC8public static final intSTRICT2048public static final intSYNCHRONIZED32public static final intTRANSIENT128public static final intVOLATILE64

2、构造方法中的参数类型可能是基本数据类型或是我们自定义的类的类型。最上面强调基本类型也是Class类的实例。所以此处可以用Class来接收参数的类类型,最后获取参数的名称。

运行结果:

全部的构造方法——直接输出:public com.xj.Person(java.lang.String,int)全部的构造方法——直接输出:public com.xj.Person(java.lang.String)全部的构造方法——直接输出:public com.xj.Person()全部构造方法——手动设置:public com.xj.Person(java.lang.String arg0,int arg1)全部构造方法——手动设置:public com.xj.Person(java.lang.String arg0)全部构造方法——手动设置:public com.xj.Person()

4、取得全部的方法

取得类中的方法和取得类中的构造函数类似。方法由修饰符、返回值类型、方法名、参数类型、异常声明组成。

  • 直接输出方法

Method methods_auto[]=c1.getMethods();for(Method method:methods_auto){     System.out.println("全部方法————直接输出:"+method);}

  • 手动输出 手动拼接,方法由 访问权限 返回值类型 方法名称(参数类型) throws 异常类型

Method methods_hand[]=c1.getMethods();for(Method method:methods_hand){        System.out.print("全部方法————手动配置:");           //访问权限        System.out.print(Modifier.toString(method.getModifiers())+" ");          //返回值类型        Class returnType=method.getReturnType();        System.out.print(returnType.getName()+" ");           //方法名称        System.out.print(method.getName()+"(");          //参数类型        Class parameterTypes[]=method.getParameterTypes();        for(int i=0;i<parameterTypes.length;i++){               System.out.print(parameterTypes[i].getName()+" arg"+i);               if(i<parameterTypes.length-1){                    System.out.print(",");              }        }        System.out.print(")");       //抛出异常       Class exceptionTypes[]=method.getExceptionTypes();       for(int i=0;i<exceptionTypes.length;i++){            System.out.print(" throws "+exceptionTypes[i].getName());            if(i<exceptionTypes.length-1){                System.out.print(",");           }       }       System.out.println();}

5、取得全部属性

说明:属性是Field类的对象。

/**getFields()获取接口,父类,超类中的公共属性。* getDeclaredFields():获取本类的全部属性。* *///属性修饰符 属性类型 属性名称Field fields[]=c1.getDeclaredFields();System.out.println("本类中属性:");for(Field field:fields){//修饰符System.out.print(Modifier.toString(field.getModifiers())+" ");//属性类型Class fieldType=field.getType();System.out.print(fieldType.getName()+" ");//属性的名称System.out.println(field.getName()+";");}//取得公共的属性Field field2[]=c1.getFields();System.out.println("公共属性:");for(Field field:field2){//修饰符System.out.print(Modifier.toString(field.getModifiers())+" ");//属性类型System.out.print(field.getType().getName()+" ");//属性名称System.out.println(field.getName()+";");}
这里面对getFields()方法与getDeclaredFields()方法进行了区别

运行结果:

本类中属性:private java.lang.String name;private int age;公共属性:public static final java.lang.String NATIONAL;public static final java.lang.String AUTHOR;
这里可以发现getDeclaredFields方法获取的是本类中所有的属性,getFIelds方法获取的是本类,父类,超类中所有公共的属性。


全部代码如下


这里仿照了Person类的结构给出了一点点的仿照

package com.xj;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;public class ClassDemo {public static void main(String[] args) {Class c1=null;try {c1=Class.forName("com.xj.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}//取得类所实现的全部接口Class infas[]=c1.getInterfaces();for(Class infa:infas){System.out.println("实现的接口名称:"+infa.getName());}//取得父类 因为只能继承一个父类,如果没有明确继承某个父类那么默认继承ObjectClass superClass=c1.getSuperclass();System.out.println("继承的父类:"+superClass);//取得全部构造方法//取得全部构造方法————直接输出Constructor对象得到的信息Constructor constructors_auto[]=c1.getConstructors();for(Constructor constructor:constructors_auto){System.out.println("全部的构造方法——直接输出:"+constructor);}System.out.println("--------------------------------------");//取得全部构造方法————手工拼凑 构造方法的组成是由  访问权限  方法名称(参数类型)组成的。Constructor constructors_hand[]=c1.getConstructors();for(Constructor constructor:constructors_hand){System.out.print("全部构造方法——手动设置:");//访问权限System.out.print(Modifier.toString(constructor.getModifiers())+" ");//方法名称System.out.print(constructor.getName()+"(");//构造方法中的参数   Class parameterTypes[]=constructor.getParameterTypes();//参数类型for(int i=0;i<parameterTypes.length;i++){System.out.print(parameterTypes[i].getName()+" arg"+i);if(i<parameterTypes.length-1){System.out.print(",");}}System.out.println(")");}//取得全部方法//取得全部的方法————直接输出方法Method methods_auto[]=c1.getMethods();for(Method method:methods_auto){System.out.println("全部方法————直接输出:"+method);}System.out.println("-------------------------");//取得全部方法————手动输出 手动拼接,方法由 访问权限 返回值类型  方法名称(参数类型) throws 异常类型Method methods_hand[]=c1.getMethods();for(Method method:methods_hand){System.out.print("全部方法————手动配置:");//访问权限System.out.print(Modifier.toString(method.getModifiers())+" ");//返回值类型Class returnType=method.getReturnType();System.out.print(returnType.getName()+" ");//方法名称System.out.print(method.getName()+"(");//参数类型Class parameterTypes[]=method.getParameterTypes();for(int i=0;i<parameterTypes.length;i++){System.out.print(parameterTypes[i].getName()+" arg"+i);if(i<parameterTypes.length-1){System.out.print(",");}}System.out.print(")");//抛出异常Class exceptionTypes[]=method.getExceptionTypes();for(int i=0;i<exceptionTypes.length;i++){System.out.print(" throws "+exceptionTypes[i].getName());if(i<exceptionTypes.length-1){System.out.print(",");}}System.out.println();}//取得全部的属性/**getFields()获取接口,父类,超类中的公共属性。 * getDeclaredFields():获取本类的全部属性。 * *///属性修饰符  属性类型   属性名称Field fields[]=c1.getDeclaredFields();System.out.println("本类中属性:");for(Field field:fields){//修饰符System.out.print(Modifier.toString(field.getModifiers())+" ");//属性类型Class fieldType=field.getType();System.out.print(fieldType.getName()+" ");//属性的名称System.out.println(field.getName()+";");}//取得公共的属性Field field2[]=c1.getFields();System.out.println("公共属性:");for(Field field:field2){//修饰符System.out.print(Modifier.toString(field.getModifiers())+" ");//属性类型System.out.print(field.getType().getName()+" ");//属性名称System.out.println(field.getName()+";");}System.out.println("列出Person类的结构");//类的修饰符System.out.print(Modifier.toString(c1.getModifiers())+" class ");//类的名称System.out.print(c1.getSimpleName()+" ");//Person继承的类Class factoryClass=c1.getSuperclass();if(factoryClass!=null){System.out.print("extends "+factoryClass.getSimpleName()+" ");}//Person类实现的接口Class factoryInterfaces[]=c1.getInterfaces();if(factoryInterfaces.length!=0){for(int i=0;i<factoryInterfaces.length;i++){System.out.print("implements "+factoryInterfaces[i].getSimpleName());}}System.out.println("{");//本类中的属性Field fields_person[]=c1.getDeclaredFields();for(Field field:fields_person){//修饰符//注意这反斜杠System.out.print("\t"+Modifier.toString(field.getModifiers())+" ");//属性类型Class fieldType=field.getType();System.out.print(fieldType.getSimpleName()+" ");//属性的名称System.out.println(field.getName()+";");}System.out.println();//类中的构造函数Constructor constructors[]=c1.getDeclaredConstructors();for(Constructor constructor:constructors){//修饰符System.out.print("\t"+Modifier.toString(constructor.getModifiers())+" ");//方法名System.out.print(constructor.getName()+"(");//参数Class parameTerTypes[]=constructor.getParameterTypes();for(int i=0;i<parameTerTypes.length;i++){System.out.print(parameTerTypes[i].getSimpleName());if(i<parameTerTypes.length-1){System.out.print(",");}}System.out.println(")");}System.out.println();//方法Method methods[]=c1.getDeclaredMethods();//获取本类中的方法for(Method method:methods){//修饰符System.out.print("\t"+Modifier.toString(method.getModifiers())+" ");//返回值类型Class returnType=method.getReturnType();System.out.print(returnType.getSimpleName()+" ");//方法名称System.out.print(method.getName()+"(");//参数Class parameterTypes[]=method.getParameterTypes();for(int i=0;i<parameterTypes.length;i++){System.out.print(parameterTypes[i].getSimpleName());if(i<parameterTypes.length-1){System.out.print(",");}}System.out.println(")");}System.out.println("}");}}interface China{public static final String NATIONAL="China";public static final String AUTHOR="张三";public void sayChina();public String sayHello(String name,int age);}class Person implements China{private String name;private int age;//构造函数public Person() {super();}public Person(String name) {super();this.name = name;}public Person(String name, int age) {super();this.name = name;this.age = age;}//set与get方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//继承方法@Overridepublic void sayChina() {}@Overridepublic String sayHello(String name, int age) {return null;}}

运行结果:

实现的接口名称:com.xj.China继承的父类:class java.lang.Object全部的构造方法——直接输出:public com.xj.Person(java.lang.String,int)全部的构造方法——直接输出:public com.xj.Person(java.lang.String)全部的构造方法——直接输出:public com.xj.Person()--------------------------------------全部构造方法——手动设置:public com.xj.Person(java.lang.String arg0,int arg1)全部构造方法——手动设置:public com.xj.Person(java.lang.String arg0)全部构造方法——手动设置:public com.xj.Person()全部方法————直接输出:public java.lang.String com.xj.Person.getName()全部方法————直接输出:public void com.xj.Person.setName(java.lang.String)全部方法————直接输出:public void com.xj.Person.setAge(int)全部方法————直接输出:public java.lang.String com.xj.Person.sayHello(java.lang.String,int)全部方法————直接输出:public int com.xj.Person.getAge()全部方法————直接输出:public void com.xj.Person.sayChina()全部方法————直接输出:public final void java.lang.Object.wait() throws java.lang.InterruptedException全部方法————直接输出:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException全部方法————直接输出:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException全部方法————直接输出:public boolean java.lang.Object.equals(java.lang.Object)全部方法————直接输出:public java.lang.String java.lang.Object.toString()全部方法————直接输出:public native int java.lang.Object.hashCode()全部方法————直接输出:public final native java.lang.Class java.lang.Object.getClass()全部方法————直接输出:public final native void java.lang.Object.notify()全部方法————直接输出:public final native void java.lang.Object.notifyAll()-------------------------全部方法————手动配置:public java.lang.String getName()全部方法————手动配置:public void setName(java.lang.String arg0)全部方法————手动配置:public void setAge(int arg0)全部方法————手动配置:public java.lang.String sayHello(java.lang.String arg0,int arg1)全部方法————手动配置:public int getAge()全部方法————手动配置:public void sayChina()全部方法————手动配置:public final void wait() throws java.lang.InterruptedException全部方法————手动配置:public final void wait(long arg0,int arg1) throws java.lang.InterruptedException全部方法————手动配置:public final native void wait(long arg0) throws java.lang.InterruptedException全部方法————手动配置:public boolean equals(java.lang.Object arg0)全部方法————手动配置:public java.lang.String toString()全部方法————手动配置:public native int hashCode()全部方法————手动配置:public final native java.lang.Class getClass()全部方法————手动配置:public final native void notify()全部方法————手动配置:public final native void notifyAll()本类中属性:private java.lang.String name;private int age;公共属性:public static final java.lang.String NATIONAL;public static final java.lang.String AUTHOR;列出Person类的结构 class Person extends Object implements China{private String name;private int age;public com.xj.Person(String,int)public com.xj.Person(String)public com.xj.Person()public String getName()public void setName(String)public void setAge(int)public String sayHello(String,int)public int getAge()public void sayChina()}


END.