好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

超详细解释Java反射

之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前java篇的基础上再写一篇有关反射的内容,还是以实际的程序为主,了解反射是做什么的、应该怎么用。

一、什么是反射

反射就是把java类中的各个成分映射成一个个的java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫java的反射机制。

1. 反射机制的功能

java反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类。 在运行时构造任意一个类的对象。 在运行时判断任意一个类所具有的成员变量和方法。 在运行时调用任意一个对象的方法。 生成动态代理。  

2. 实现反射机制的类

java中主要由以下的类来实现java反射机制(这些类都位于java.lang.reflect包中):

class类:代表一个类。 field类:代表类的成员变量(成员变量也称为类的属性)。 method类:代表类的方法。 constructor类:代表类的构造方法。 array类:提供了动态创建数组,以及访问数组的元素的静态方法。

二、反射的使用

下面分步说明以下如何通过反射获取我们需要的内容。

我们先随意写一个customer类(就是一个po类),然后看看如何通过反射对这个类进行操作。

1. customer类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

  之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前java篇的基础上再写一篇有关反射的内容,还是以实际的程序为主,了解反射是做什么的、应该怎么用。

一、什么是反射

  反射就是把java类中的各个成分映射成一个个的java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫java的反射机制。

   1 . 反射机制的功能

  java反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类。在运行时构造任意一个类的对象。在运行时判断任意一个类所具有的成员变量和方法。在运行时调用任意一个对象的方法。生成动态代理。   2 . 实现反射机制的类

    java中主要由以下的类来实现java反射机制(这些类都位于java.lang.reflect包中):

class 类:代表一个类。 field类:代表类的成员变量(成员变量也称为类的属性)。

method类:代表类的方法。

constructor类:代表类的构造方法。

array类:提供了动态创建数组,以及访问数组的元素的静态方法。

二、反射的使用

  下面分步说明以下如何通过反射获取我们需要的内容。

  我们先随意写一个customer类(就是一个po类),然后看看如何通过反射对这个类进行操作。

   1 . customer类

  1 public class customer { 2       3      private long id; 4      private string name; 5      private int age; 6         7      public customer() {} 8       9      public customer(string name, int age) { 10          this .name = name; 11          this .age = age; 12      } 13        14      public long getid() { 15          return id; 16      } 17      public void setid( long id) { 18          this .id=id; 19      } 20      public string getname() { 21          return name; 22      } 23      public void setname(string name) { 24          this .name=name; 25      } 26      public int getage() { 27          return age; 28      } 29      public void setage( int age) { 30          this .age=age; 31      } 32 33 }

     2 . reflecttester类

  这个类用来演示reflection api的基本使用方法。这里自定义的copy方法是用来创建一个和参数objcet同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将其返回。

  1 import java.lang.reflect.field; 2 import java.lang.reflect.method; 3   4 public class reflecttester { 5       6      public object copy(object object) throws exception{ 7          //获得对象的类型 8         class classtype=object.getclass(); 9         system.out.println("class:"+classtype.getname());10 11         //通过默认构造方法创建一个新的对象12         object objectcopy=classtype.getconstructor(new class[]{}).newinstance(new object[]{});13 14         //获得对象的所有属性15         field fields[]=classtype.getdeclaredfields();16 17         for(int i=0; i<fields.length;i++){18               field field=fields[i];19 20               string fieldname=field.getname();21               string firstletter=fieldname.substring(0,1).touppercase();22               //获得和属性对应的getxxx()方法的名字23               string getmethodname="get"+firstletter+fieldname.substring(1);24               //获得和属性对应的setxxx()方法的名字25               string setmethodname="set"+firstletter+fieldname.substring(1);26 27               //获得和属性对应的getxxx()方法28               method getmethod=classtype.getmethod(getmethodname,new class[]{});29               //获得和属性对应的setxxx()方法30               method setmethod=classtype.getmethod(setmethodname,new class[]{field.gettype()});31 32               //调用原对象的getxxx()方法33               object value=getmethod.invoke(object,new object[]{});34               system.out.println(fieldname+":"+value);35               //调用拷贝对象的setxxx()方法36              setmethod.invoke(objectcopy,new object[]{value});37         }38         return objectcopy;39      }40 41 }

  下面分析一下上述代码。

  首先,通过object类中的getclass()方法获取对象的类型。

class classtype=object.getclass();

  而 class 类是reflection api中的核心类,主要方法如下:

getname():获得类的完整名字。 getfields():获得类的 public 类型的属性。

getdeclaredfields():获得类的所有属性。

getmethods():获得类的 public 类型的方法。

getdeclaredmethods():获得类的所有方法。

getmethod(string name, class [] parametertypes):获得类的特定方法,name参数指定方法的名字,parametertypes参数指定方法的参数类型。

getconstrutors():获得类的 public 类型的构造方法。

getconstrutor( class [] parametertypes):获得类的特定构造方法,parametertypes参数指定构造方法的参数类型。

newinstance():通过类的不带参数的构造方法创建这个类的一个对象。

  第二步,通过默认构造方法创建一个新的对象,即先调用 class 类的getconstructor()方法获得一个constructor对象,它代表默认的构造方法,然后调用constructor对象的newinstance()方法构造一个实例。

object objectcopy=classtype.getconstructor( new class []{}).newinstance( new object[]{});

  第三步,获得对象的所有属性,即通过 class 类的getdeclaredfields()方法返回类的所有属性,包括 public 、 protected 、 default 和 private 访问级别的属性,

field fields[]=classtype.getdeclaredfields();

  第四步,获得每个属性相应的get/set方法,然后执行这些方法,把原来的对象属性拷贝到新的对象中。

  这里我们可以写一个invoketester的类,然后运用反射机制调用一个invoketester对象的add()方法(自定义方法),如add()方法的两个参数为 int 类型,那么获取表示add()方法的method对象代码如下:

method addmethod=classtype.getmethod( "add" , new class []{ int . class , int . class });

    上述代码中也有用到method的invoke方法,其接收参数必须为对象,如果参数为基本数据类型,必须转换为相应的包装类型的对象,如 int 要转换为integer。而invoke方法的返回值总是对象,如果实际被调用的方法的返回类型是基本数据类型,那么invoke方法会将其转换为相应的包装类型的对象,再将其返回。

  下面简单测试一下,具体的方法调用如上面提到的add方法,可自行编写(具体实例见下篇):

1 public static void main(string[] args) throws exception { 2   customer customer = new customer(); 3   customer.setid(10l); 4   customer.setname( "adam" ); 5   customer.setage( 3 ); 6          7    new reflecttester().copy(customer); 8 }  

    运行结果如下:

  

三、具体实例

  下面我们尝试着通过反射机制对一个jar包中的类进行分析,把类中所有的属性和方法提取出来,并写入到一个文件里中。

  目录结构如下:

  

   1 . reflexdemo类

  主要代码部分,通过反射获取类、属性及方法。

  1 import java.io.file; 2 import java.lang.reflect.field; 3 import java.lang.reflect.method; 4 import java.net.url; 5 import java.net.urlclassloader; 6 import java.util.enumeration; 7 import java.util.jar.jarentry; 8 import java.util.jar.jarfile; 9 10 /**11  * @classname: reflexdemo12  * @description: 通过反射获取类、属性及方法13  * @author adamjwh14  * @date 2018年5月28日15  *16  */ 17 public class reflexdemo { 18 19      private static stringbuffer sbuffer; 20      21      public static void getjar(string jar) throws exception { 22          try { 23              file file = new file(jar); 24              url url = file.touri().tourl(); 25              urlclassloader classloader = new urlclassloader( new url[] { url }, 26                      thread.currentthread().getcontextclassloader()); 27 28              jarfile jarfile = new jarfile(jar); 29              enumeration<jarentry> enumeration = jarfile.entries(); 30              jarentry jarentry; 31              32              sbuffer = new stringbuffer();    //存数据33 34             while (enumeration.hasmoreelements()) {35                 jarentry = enumeration.nextelement();36 37                 if (jarentry.getname().indexof("meta-inf") < 0) {38                     string classfullname = jarentry.getname();39                     if (classfullname.indexof(".class") < 0) {40                         classfullname = classfullname.substring(0, classfullname.length() - 1);41                     } else {42                         // 去除后缀.class,获得类名43                         string classname = classfullname.substring(0, classfullname.length() - 6).replace("/", ".");44                         class<?> myclass = classloader.loadclass(classname);45                         sbuffer.append("类名\t:" + classname);46                         system.out.println("类名\t:" + classname);47 48                         // 获得属性名49                         class<?> clazz = class.forname(classname);50                         field[] fields = clazz.getdeclaredfields();51                         for (field field : fields) {52                             sbuffer.append("属性名\t:" + field.getname() + "\n");53                             system.out.println("属性名\t:" + field.getname());54                             sbuffer.append("-属性类型\t:" + field.gettype() + "\n");55                             system.out.println("-属性类型\t:" + field.gettype());56                         }57 58                         // 获得方法名59                         method[] methods = myclass.getmethods();60                         for (method method : methods) {61                             if (method.tostring().indexof(classname) > 0) {62                                 sbuffer.append("方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)) + "\n");63                                 system.out.println("方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)));64                             }65                         }66                         sbuffer.append("--------------------------------------------------------------------------------" + "\n");67                         system.out.println("--------------------------------------------------------------------------------");68                     }69                 }70             }71         } catch (exception e) {72             e.printstacktrace();73         } finally {74             sbuffer.append("end");75             system.out.println("end");76             77             writefile.write(sbuffer);    //写文件78         }79     }80 81 }

   2 . writefile类

  进行写文件操作。

  1 import java.io.bufferedwriter; 2 import java.io.file; 3 import java.io.filewriter; 4   5 /** 6  * @classname: writefile 7  * @description: 写文件操作 8  * @author adamjwh 9  * @date 2018年5月28日10  *11  */ 12 public class writefile { 13 14      private static string pathname = "src/com/adamjwh/jnp/ex14/out.txt" ; 15      16      public static void write(stringbuffer sbuffer) throws exception { 17          file file = new file(pathname); 18          bufferedwriter bw = new bufferedwriter( new filewriter(file)); 19          20          bw.write(sbuffer.tostring()); 21          bw.close(); 22      } 23      24 }

   3 . main类

  这里我们需要在项目下新建一个lib文件夹,然后将要解析的jar包放入其中,比如这里我们放入jdk的dt.jar。目录结构如下:

  

  执行程序:

  1 /** 2  * @classname: main 3  * @description:  4  * @author adamjwh 5  * @date 2018年5月28日 6  * 7  */ 8 public class main { 9      10      private static string jar = "lib/dt.jar" ; 11      12      public static void main(string[] args) throws exception { 13          reflexdemo.getjar(jar); 14      } 15 16 }

  运行结果如下:

  

2. reflecttester类

这个类用来演示reflection api的基本使用方法。这里自定义的copy方法是用来创建一个和参数objcet同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将其返回。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

  之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前java篇的基础上再写一篇有关反射的内容,还是以实际的程序为主,了解反射是做什么的、应该怎么用。

一、什么是反射

  反射就是把java类中的各个成分映射成一个个的java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫java的反射机制。

   1 . 反射机制的功能

  java反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类。在运行时构造任意一个类的对象。在运行时判断任意一个类所具有的成员变量和方法。在运行时调用任意一个对象的方法。生成动态代理。   2 . 实现反射机制的类

    java中主要由以下的类来实现java反射机制(这些类都位于java.lang.reflect包中):

class 类:代表一个类。 field类:代表类的成员变量(成员变量也称为类的属性)。

method类:代表类的方法。

constructor类:代表类的构造方法。

array类:提供了动态创建数组,以及访问数组的元素的静态方法。

二、反射的使用

  下面分步说明以下如何通过反射获取我们需要的内容。

  我们先随意写一个customer类(就是一个po类),然后看看如何通过反射对这个类进行操作。

   1 . customer类

  1 public class customer { 2       3      private long id; 4      private string name; 5      private int age; 6         7      public customer() {} 8       9      public customer(string name, int age) { 10          this .name = name; 11          this .age = age; 12      } 13        14      public long getid() { 15          return id; 16      } 17      public void setid( long id) { 18          this .id=id; 19      } 20      public string getname() { 21          return name; 22      } 23      public void setname(string name) { 24          this .name=name; 25      } 26      public int getage() { 27          return age; 28      } 29      public void setage( int age) { 30          this .age=age; 31      } 32 33 }

     2 . reflecttester类

  这个类用来演示reflection api的基本使用方法。这里自定义的copy方法是用来创建一个和参数objcet同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将其返回。

  1 import java.lang.reflect.field; 2 import java.lang.reflect.method; 3   4 public class reflecttester { 5       6      public object copy(object object) throws exception{ 7          //获得对象的类型 8         class classtype=object.getclass(); 9         system.out.println("class:"+classtype.getname());10 11         //通过默认构造方法创建一个新的对象12         object objectcopy=classtype.getconstructor(new class[]{}).newinstance(new object[]{});13 14         //获得对象的所有属性15         field fields[]=classtype.getdeclaredfields();16 17         for(int i=0; i<fields.length;i++){18               field field=fields[i];19 20               string fieldname=field.getname();21               string firstletter=fieldname.substring(0,1).touppercase();22               //获得和属性对应的getxxx()方法的名字23               string getmethodname="get"+firstletter+fieldname.substring(1);24               //获得和属性对应的setxxx()方法的名字25               string setmethodname="set"+firstletter+fieldname.substring(1);26 27               //获得和属性对应的getxxx()方法28               method getmethod=classtype.getmethod(getmethodname,new class[]{});29               //获得和属性对应的setxxx()方法30               method setmethod=classtype.getmethod(setmethodname,new class[]{field.gettype()});31 32               //调用原对象的getxxx()方法33               object value=getmethod.invoke(object,new object[]{});34               system.out.println(fieldname+":"+value);35               //调用拷贝对象的setxxx()方法36              setmethod.invoke(objectcopy,new object[]{value});37         }38         return objectcopy;39      }40 41 }

  下面分析一下上述代码。

  首先,通过object类中的getclass()方法获取对象的类型。

class classtype=object.getclass();

  而 class 类是reflection api中的核心类,主要方法如下:

getname():获得类的完整名字。 getfields():获得类的 public 类型的属性。

getdeclaredfields():获得类的所有属性。

getmethods():获得类的 public 类型的方法。

getdeclaredmethods():获得类的所有方法。

getmethod(string name, class [] parametertypes):获得类的特定方法,name参数指定方法的名字,parametertypes参数指定方法的参数类型。

getconstrutors():获得类的 public 类型的构造方法。

getconstrutor( class [] parametertypes):获得类的特定构造方法,parametertypes参数指定构造方法的参数类型。

newinstance():通过类的不带参数的构造方法创建这个类的一个对象。

  第二步,通过默认构造方法创建一个新的对象,即先调用 class 类的getconstructor()方法获得一个constructor对象,它代表默认的构造方法,然后调用constructor对象的newinstance()方法构造一个实例。

object objectcopy=classtype.getconstructor( new class []{}).newinstance( new object[]{});

  第三步,获得对象的所有属性,即通过 class 类的getdeclaredfields()方法返回类的所有属性,包括 public 、 protected 、 default 和 private 访问级别的属性,

field fields[]=classtype.getdeclaredfields();

  第四步,获得每个属性相应的get/set方法,然后执行这些方法,把原来的对象属性拷贝到新的对象中。

  这里我们可以写一个invoketester的类,然后运用反射机制调用一个invoketester对象的add()方法(自定义方法),如add()方法的两个参数为 int 类型,那么获取表示add()方法的method对象代码如下:

method addmethod=classtype.getmethod( "add" , new class []{ int . class , int . class });

    上述代码中也有用到method的invoke方法,其接收参数必须为对象,如果参数为基本数据类型,必须转换为相应的包装类型的对象,如 int 要转换为integer。而invoke方法的返回值总是对象,如果实际被调用的方法的返回类型是基本数据类型,那么invoke方法会将其转换为相应的包装类型的对象,再将其返回。

  下面简单测试一下,具体的方法调用如上面提到的add方法,可自行编写(具体实例见下篇):

1 public static void main(string[] args) throws exception { 2   customer customer = new customer(); 3   customer.setid(10l); 4   customer.setname( "adam" ); 5   customer.setage( 3 ); 6          7    new reflecttester().copy(customer); 8 }  

    运行结果如下:

  

三、具体实例

  下面我们尝试着通过反射机制对一个jar包中的类进行分析,把类中所有的属性和方法提取出来,并写入到一个文件里中。

  目录结构如下:

  

   1 . reflexdemo类

  主要代码部分,通过反射获取类、属性及方法。

  1 import java.io.file; 2 import java.lang.reflect.field; 3 import java.lang.reflect.method; 4 import java.net.url; 5 import java.net.urlclassloader; 6 import java.util.enumeration; 7 import java.util.jar.jarentry; 8 import java.util.jar.jarfile; 9 10 /**11  * @classname: reflexdemo12  * @description: 通过反射获取类、属性及方法13  * @author adamjwh14  * @date 2018年5月28日15  *16  */ 17 public class reflexdemo { 18 19      private static stringbuffer sbuffer; 20      21      public static void getjar(string jar) throws exception { 22          try { 23              file file = new file(jar); 24              url url = file.touri().tourl(); 25              urlclassloader classloader = new urlclassloader( new url[] { url }, 26                      thread.currentthread().getcontextclassloader()); 27 28              jarfile jarfile = new jarfile(jar); 29              enumeration<jarentry> enumeration = jarfile.entries(); 30              jarentry jarentry; 31              32              sbuffer = new stringbuffer();    //存数据33 34             while (enumeration.hasmoreelements()) {35                 jarentry = enumeration.nextelement();36 37                 if (jarentry.getname().indexof("meta-inf") < 0) {38                     string classfullname = jarentry.getname();39                     if (classfullname.indexof(".class") < 0) {40                         classfullname = classfullname.substring(0, classfullname.length() - 1);41                     } else {42                         // 去除后缀.class,获得类名43                         string classname = classfullname.substring(0, classfullname.length() - 6).replace("/", ".");44                         class<?> myclass = classloader.loadclass(classname);45                         sbuffer.append("类名\t:" + classname);46                         system.out.println("类名\t:" + classname);47 48                         // 获得属性名49                         class<?> clazz = class.forname(classname);50                         field[] fields = clazz.getdeclaredfields();51                         for (field field : fields) {52                             sbuffer.append("属性名\t:" + field.getname() + "\n");53                             system.out.println("属性名\t:" + field.getname());54                             sbuffer.append("-属性类型\t:" + field.gettype() + "\n");55                             system.out.println("-属性类型\t:" + field.gettype());56                         }57 58                         // 获得方法名59                         method[] methods = myclass.getmethods();60                         for (method method : methods) {61                             if (method.tostring().indexof(classname) > 0) {62                                 sbuffer.append("方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)) + "\n");63                                 system.out.println("方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)));64                             }65                         }66                         sbuffer.append("--------------------------------------------------------------------------------" + "\n");67                         system.out.println("--------------------------------------------------------------------------------");68                     }69                 }70             }71         } catch (exception e) {72             e.printstacktrace();73         } finally {74             sbuffer.append("end");75             system.out.println("end");76             77             writefile.write(sbuffer);    //写文件78         }79     }80 81 }

   2 . writefile类

  进行写文件操作。

  1 import java.io.bufferedwriter; 2 import java.io.file; 3 import java.io.filewriter; 4   5 /** 6  * @classname: writefile 7  * @description: 写文件操作 8  * @author adamjwh 9  * @date 2018年5月28日10  *11  */ 12 public class writefile { 13 14      private static string pathname = "src/com/adamjwh/jnp/ex14/out.txt" ; 15      16      public static void write(stringbuffer sbuffer) throws exception { 17          file file = new file(pathname); 18          bufferedwriter bw = new bufferedwriter( new filewriter(file)); 19          20          bw.write(sbuffer.tostring()); 21          bw.close(); 22      } 23      24 }

   3 . main类

  这里我们需要在项目下新建一个lib文件夹,然后将要解析的jar包放入其中,比如这里我们放入jdk的dt.jar。目录结构如下:

  

  执行程序:

  1 /** 2  * @classname: main 3  * @description:  4  * @author adamjwh 5  * @date 2018年5月28日 6  * 7  */ 8 public class main { 9      10      private static string jar = "lib/dt.jar" ; 11      12      public static void main(string[] args) throws exception { 13          reflexdemo.getjar(jar); 14      } 15 16 }

  运行结果如下:

  

下面分析一下上述代码。

首先,通过object类中的getclass()方法获取对象的类型。

?

1

class classtype=object.getclass();

而class类是reflection api中的核心类,主要方法如下:

getname():获得类的完整名字。 getfields():获得类的public类型的属性。 getdeclaredfields():获得类的所有属性。 getmethods():获得类的public类型的方法。 getdeclaredmethods():获得类的所有方法。 getmethod(string name, class[] parametertypes):获得类的特定方法,name参数指定方法的名字,parametertypes参数指定方法的参数类型。 getconstrutors():获得类的public类型的构造方法。 getconstrutor(class[] parametertypes):获得类的特定构造方法,parametertypes参数指定构造方法的参数类型。 newinstance():通过类的不带参数的构造方法创建这个类的一个对象。

第二步,通过默认构造方法创建一个新的对象,即先调用class类的getconstructor()方法获得一个constructor对象,它代表默认的构造方法,然后调用constructor对象的newinstance()方法构造一个实例。

?

1

object objectcopy=classtype.getconstructor( new class []{}).newinstance( new object[]{});

第三步,获得对象的所有属性,即通过class类的getdeclaredfields()方法返回类的所有属性,包括public、protected、default和private访问级别的属性,

?

1

field fields[]=classtype.getdeclaredfields();

第四步,获得每个属性相应的get/set方法,然后执行这些方法,把原来的对象属性拷贝到新的对象中。

这里我们可以写一个invoketester的类,然后运用反射机制调用一个invoketester对象的add()方法(自定义方法),如add()方法的两个参数为int类型,那么获取表示add()方法的method对象代码如下:

?

1

method addmethod=classtype.getmethod( "add" , new class []{ int . class , int . class });

上述代码中也有用到method的invoke方法,其接收参数必须为对象,如果参数为基本数据类型,必须转换为相应的包装类型的对象,如int要转换为integer。而invoke方法的返回值总是对象,如果实际被调用的方法的返回类型是基本数据类型,那么invoke方法会将其转换为相应的包装类型的对象,再将其返回。

下面简单测试一下,具体的方法调用如上面提到的add方法,可自行编写(具体实例见下篇):

?

1

2

3

4

5

6

7

public static void main(string[] args) throws exception {

  customer customer = new customer();

  customer.setid(10l);

  customer.setname( "adam" );

  customer.setage( 3 );

   new reflecttester().copy(customer);

}

运行结果如下:

三、具体实例

下面我们尝试着通过反射机制对一个jar包中的类进行分析,把类中所有的属性和方法提取出来,并写入到一个文件里中。

目录结构如下:

1. reflexdemo类

主要代码部分,通过反射获取类、属性及方法。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

import java.io.file;

import java.lang.reflect.field;

import java.lang.reflect.method;

import java.net.url;

import java.net.urlclassloader;

import java.util.enumeration;

import java.util.jar.jarentry;

import java.util.jar.jarfile;

/**

  * @classname: reflexdemo

  * @description: 通过反射获取类、属性及方法

  * @author adamjwh

  * @date 2018年5月28日

  *

  */

public class reflexdemo {

     private static stringbuffer sbuffer;

     public static void getjar(string jar) throws exception {

         try {

             file file = new file(jar);

             url url = file.touri().tourl();

             urlclassloader classloader = new urlclassloader( new url[] { url },

                     thread.currentthread().getcontextclassloader());

             jarfile jarfile = new jarfile(jar);

             enumeration<jarentry> enumeration = jarfile.entries();

             jarentry jarentry;

             sbuffer = new stringbuffer();    //存数据

             while (enumeration.hasmoreelements()) {

                 jarentry = enumeration.nextelement();

                 if (jarentry.getname().indexof( "meta-inf" ) < 0 ) {

                     string classfullname = jarentry.getname();

                     if (classfullname.indexof( ".class" ) < 0 ) {

                         classfullname = classfullname.substring( 0 , classfullname.length() - 1 );

                     } else {

                         // 去除后缀.class,获得类名

                         string classname = classfullname.substring( 0 , classfullname.length() - 6 ).replace( "/" , "." );

                         class <?> myclass = classloader.loadclass(classname);

                         sbuffer.append( "类名\t:" + classname);

                         system.out.println( "类名\t:" + classname);

                         // 获得属性名

                         class <?> clazz = class .forname(classname);

                         field[] fields = clazz.getdeclaredfields();

                         for (field field : fields) {

                             sbuffer.append( "属性名\t:" + field.getname() + "\n" );

                             system.out.println( "属性名\t:" + field.getname());

                             sbuffer.append( "-属性类型\t:" + field.gettype() + "\n" );

                             system.out.println( "-属性类型\t:" + field.gettype());

                         }

                         // 获得方法名

                         method[] methods = myclass.getmethods();

                         for (method method : methods) {

                             if (method.tostring().indexof(classname) > 0 ) {

                                 sbuffer.append( "方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)) + "\n" );

                                 system.out.println( "方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)));

                             }

                         }

                         sbuffer.append( "--------------------------------------------------------------------------------" + "\n" );

                         system.out.println( "--------------------------------------------------------------------------------" );

                     }

                 }

             }

         } catch (exception e) {

             e.printstacktrace();

         } finally {

             sbuffer.append( "end" );

             system.out.println( "end" );

             writefile.write(sbuffer);    //写文件

         }

     }

}

2. writefile类

进行写文件操作。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

import java.io.file;

import java.lang.reflect.field;

import java.lang.reflect.method;

import java.net.url;

import java.net.urlclassloader;

import java.util.enumeration;

import java.util.jar.jarentry;

import java.util.jar.jarfile;

/**

  * @classname: reflexdemo

  * @description: 通过反射获取类、属性及方法

  * @author adamjwh

  * @date 2018年5月28日

  *

  */

public class reflexdemo {

     private static stringbuffer sbuffer;

     public static void getjar(string jar) throws exception {

         try {

             file file = new file(jar);

             url url = file.touri().tourl();

             urlclassloader classloader = new urlclassloader( new url[] { url },

                     thread.currentthread().getcontextclassloader());

             jarfile jarfile = new jarfile(jar);

             enumeration<jarentry> enumeration = jarfile.entries();

             jarentry jarentry;

             sbuffer = new stringbuffer();    //存数据

             while (enumeration.hasmoreelements()) {

                 jarentry = enumeration.nextelement();

                 if (jarentry.getname().indexof( "meta-inf" ) < 0 ) {

                     string classfullname = jarentry.getname();

                     if (classfullname.indexof( ".class" ) < 0 ) {

                         classfullname = classfullname.substring( 0 , classfullname.length() - 1 );

                     } else {

                         // 去除后缀.class,获得类名

                         string classname = classfullname.substring( 0 , classfullname.length() - 6 ).replace( "/" , "." );

                         class <?> myclass = classloader.loadclass(classname);

                         sbuffer.append( "类名\t:" + classname);

                         system.out.println( "类名\t:" + classname);

                         // 获得属性名

                         class <?> clazz = class .forname(classname);

                         field[] fields = clazz.getdeclaredfields();

                         for (field field : fields) {

                             sbuffer.append( "属性名\t:" + field.getname() + "\n" );

                             system.out.println( "属性名\t:" + field.getname());

                             sbuffer.append( "-属性类型\t:" + field.gettype() + "\n" );

                             system.out.println( "-属性类型\t:" + field.gettype());

                         }

                         // 获得方法名

                         method[] methods = myclass.getmethods();

                         for (method method : methods) {

                             if (method.tostring().indexof(classname) > 0 ) {

                                 sbuffer.append( "方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)) + "\n" );

                                 system.out.println( "方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)));

                             }

                         }

                         sbuffer.append( "--------------------------------------------------------------------------------" + "\n" );

                         system.out.println( "--------------------------------------------------------------------------------" );

                     }

                 }

             }

         } catch (exception e) {

             e.printstacktrace();

         } finally {

             sbuffer.append( "end" );

             system.out.println( "end" );

             writefile.write(sbuffer);    //写文件

         }

     }

}

3. main类

这里我们需要在项目下新建一个lib文件夹,然后将要解析的jar包放入其中,比如这里我们放入jdk的dt.jar。目录结构如下:

执行程序:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

import java.io.file;

import java.lang.reflect.field;

import java.lang.reflect.method;

import java.net.url;

import java.net.urlclassloader;

import java.util.enumeration;

import java.util.jar.jarentry;

import java.util.jar.jarfile;

/**

  * @classname: reflexdemo

  * @description: 通过反射获取类、属性及方法

  * @author adamjwh

  * @date 2018年5月28日

  *

  */

public class reflexdemo {

     private static stringbuffer sbuffer;

     public static void getjar(string jar) throws exception {

         try {

             file file = new file(jar);

             url url = file.touri().tourl();

             urlclassloader classloader = new urlclassloader( new url[] { url },

                     thread.currentthread().getcontextclassloader());

             jarfile jarfile = new jarfile(jar);

             enumeration<jarentry> enumeration = jarfile.entries();

             jarentry jarentry;

             sbuffer = new stringbuffer();    //存数据

             while (enumeration.hasmoreelements()) {

                 jarentry = enumeration.nextelement();

                 if (jarentry.getname().indexof( "meta-inf" ) < 0 ) {

                     string classfullname = jarentry.getname();

                     if (classfullname.indexof( ".class" ) < 0 ) {

                         classfullname = classfullname.substring( 0 , classfullname.length() - 1 );

                     } else {

                         // 去除后缀.class,获得类名

                         string classname = classfullname.substring( 0 , classfullname.length() - 6 ).replace( "/" , "." );

                         class <?> myclass = classloader.loadclass(classname);

                         sbuffer.append( "类名\t:" + classname);

                         system.out.println( "类名\t:" + classname);

                         // 获得属性名

                         class <?> clazz = class .forname(classname);

                         field[] fields = clazz.getdeclaredfields();

                         for (field field : fields) {

                             sbuffer.append( "属性名\t:" + field.getname() + "\n" );

                             system.out.println( "属性名\t:" + field.getname());

                             sbuffer.append( "-属性类型\t:" + field.gettype() + "\n" );

                             system.out.println( "-属性类型\t:" + field.gettype());

                         }

                         // 获得方法名

                         method[] methods = myclass.getmethods();

                         for (method method : methods) {

                             if (method.tostring().indexof(classname) > 0 ) {

                                 sbuffer.append( "方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)) + "\n" );

                                 system.out.println( "方法名\t:" + method.tostring().substring(method.tostring().indexof(classname)));

                             }

                         }

                         sbuffer.append( "--------------------------------------------------------------------------------" + "\n" );

                         system.out.println( "--------------------------------------------------------------------------------" );

                     }

                 }

             }

         } catch (exception e) {

             e.printstacktrace();

         } finally {

             sbuffer.append( "end" );

             system.out.println( "end" );

             writefile.write(sbuffer);    //写文件

         }

     }

}

运行结果如下:

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!

原文链接:https://HdhCmsTestcnblogs测试数据/adamjwh/p/9683705.html

查看更多关于超详细解释Java反射的详细内容...

  阅读:12次