之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前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://www.cnblogs.com/adamjwh/p/9683705.html