我是靠谱客的博主 谨慎马里奥,这篇文章主要介绍超详细解释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
之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前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
之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前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); //写文件 } } }

运行结果如下:

总结

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

最后

以上就是谨慎马里奥最近收集整理的关于超详细解释Java反射的全部内容,更多相关超详细解释Java反射内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(114)

评论列表共有 0 条评论

立即
投稿
返回
顶部