java反射机制详细解析 喜欢ヅ旅行 2021-09-15 02:32 324阅读 0赞 (一)什么是反射机制? 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 (二)反射机制能做什么? 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 (三)反射机制的相关API 通过一个对象获得完整的包名和类名 实例化一个类对象(使用构造函数,默认的和带参数的) 返回一个类实现的接口 取得一个类的父类 获得一个类的全部构造函数 可以通过反射调用一个类的方法 调用一个类的set和get方法 通过反射操作属性 通过反射取得并修改数组的信息 通过反射修改数组大小 就看看下面的各式各样的例子,来一步一步的看看反射都能干些什么,都能干嘛,比空谈理论强多了。 例子虽然海了去了,但是耐心看一半,估计你就赢啦。 【案例1】通过一个对象获得完整的包名和类名 **\[java\]** [view plain][] [copy][view plain] 1. package Reflect; 2. 3. /\*\* 4. \* 通过一个对象获得完整的包名和类名 5. \*/ 6. class Demo \{ 7. //other codes... 8. \} 9. 10. class hello \{ 11. public static void main(String\[\] args) \{ 12. Demo demo = new Demo(); 13. System.out.println(demo.getClass().getName()); 14. \} 15. \} 【运行结果】:Reflect.Demo 【案例2】实例化Class类对象 **\[java\]** [view plain][] [copy][view plain] 1. package Reflect; 2. 3. class Demo \{ 4. //other codes... 5. \} 6. 7. class hello \{ 8. public static void main(String\[\] args) \{ 9. Class<?> demo1 = null; 10. Class<?> demo2 = null; 11. Class<?> demo3 = null; 12. try \{ 13. //一般尽量采用这种形式 14. demo1 = Class.forName("Reflect.Demo"); 15. \} catch (Exception e) \{ 16. e.printStackTrace(); 17. \} 18. demo2 = new Demo().getClass(); 19. demo3 = Demo.class; 20. System.out.println("类名称 " + demo1.getName()); 21. System.out.println("类名称 " + demo2.getName()); 22. System.out.println("类名称 " + demo3.getName()); 23. \} 24. \} 【运行结果】: 类名称 Reflect.Demo 类名称 Reflect.Demo 类名称 Reflect.Demo 【案例3】通过Class实例化其他类的对象 通过无参构造实例化对象 **\[java\]** [view plain][] [copy][view plain] 1. package Reflect; 2. 3. class Person \{ 4. private String name; 5. private int age; 6. 7. //getters and setters 8. @Override 9. public String toString() \{ 10. return "\[" + this.name + " " + this.age + "\]"; 11. \} 12. \} 13. 14. class hello \{ 15. public static void main(String\[\] args) \{ 16. Class<?> demo = null; 17. try \{ 18. demo = Class.forName("Reflect.Person"); 19. \} catch (Exception e) \{ 20. e.printStackTrace(); 21. \} 22. Person per = null; 23. try \{ 24. per = (Person) demo.newInstance(); 25. \} catch (InstantiationException e) \{ 26. // TODO Auto-generated catch block 27. e.printStackTrace(); 28. \} catch (IllegalAccessException e) \{ 29. // TODO Auto-generated catch block 30. e.printStackTrace(); 31. \} 32. per.setName("Rollen"); 33. per.setAge(20); 34. System.out.println(per); 35. \} 36. \} 【运行结果】: \[Rollen 20\] 但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误: 比如我定义了一个构造函数: **\[java\]** [view plain][] [copy][view plain] 1. public Person(String name, int age) \{ 2. this.age = age; 3. this.name = name; 4. \} 然后继续运行上面的程序,会出现: java.lang.InstantiationException: Reflect.Person at java.lang.Class.newInstance0(Class.java:340) at java.lang.Class.newInstance(Class.java:308) at Reflect.hello.main(hello.java:39) Exception in thread "main" java.lang.NullPointerException at Reflect.hello.main(hello.java:47) 所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数 比如我的这个bug也是因为这个默认构造函数的问题,实例化对象就出错了。具体如下: [因为少了默认构造方法而引发的bug][bug] 【案例4】通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象) **\[java\]** [view plain][] [copy][view plain] 1. package Reflect; 2. 3. import java.lang.reflect.Constructor; 4. 5. class Person \{ 6. private String name; 7. private int age; 8. 9. public Person() \{ 10. \} 11. 12. public Person(String name) \{ 13. this.name = name; 14. \} 15. 16. public Person(int age) \{ 17. this.age = age; 18. \} 19. 20. public Person(String name, int age) \{ 21. this.age = age; 22. this.name = name; 23. \} 24. 25. //getters and setters 26. @Override 27. public String toString() \{ 28. return "\[" + this.name + " " + this.age + "\]"; 29. \} 30. \} 31. 32. class hello \{ 33. public static void main(String\[\] args) \{ 34. Class<?> demo = null; 35. try \{ 36. demo = Class.forName("Reflect.Person"); 37. \} catch (Exception e) \{ 38. e.printStackTrace(); 39. \} 40. Person per1 = null; 41. Person per2 = null; 42. Person per3 = null; 43. Person per4 = null; 44. //取得全部的构造函数 45. Constructor<?> cons\[\] = demo.getConstructors(); 46. try \{ 47. per1 = (Person) cons\[0\].newInstance(); 48. per2 = (Person) cons\[1\].newInstance("Rollen"); 49. per3 = (Person) cons\[2\].newInstance(20); 50. per4 = (Person) cons\[3\].newInstance("Rollen", 20); 51. \} catch (Exception e) \{ 52. e.printStackTrace(); 53. \} 54. System.out.println(per1); 55. System.out.println(per2); 56. System.out.println(per3); 57. System.out.println(per4); 58. \} 59. \} 【运行结果】: \[null 0\] \[Rollen 0\] \[null 20\] \[Rollen 20\] 【案例5】返回一个类实现的接口: **\[java\]** [view plain][] [copy][view plain] 1. package Reflect; 2. 3. interface China \{ 4. //public static final String name = "Rollen"; 5. //接口中声明前面的类型等修饰符都是多余的 6. String name = "Rollen"; 7. int age = 20; 8. void sayChina(); 9. void sayHello(String name, int age); 10. \} 11. 12. class Person implements China \{ 13. private String sex; 14. 15. public Person() \{ 16. \} 17. public Person(String sex) \{ 18. this.sex = sex; 19. \} 20. public String getSex() \{ 21. return sex; 22. \} 23. public void setSex(String sex) \{ 24. this.sex = sex; 25. \} 26. @Override 27. public void sayChina() \{ 28. System.out.println("hello ,china"); 29. \} 30. @Override 31. public void sayHello(String name, int age) \{ 32. System.out.println(name + " " + age); 33. \} 34. \} 35. 36. class hello \{ 37. public static void main(String\[\] args) \{ 38. Class<?> demo = null; 39. try \{ 40. demo = Class.forName("Reflect.Person"); 41. \} catch (Exception e) \{ 42. e.printStackTrace(); 43. \} 44. //保存所有的接口 45. Class<?> intes\[\] = demo.getInterfaces(); 46. for (int i = 0; i < intes.length; i++) \{ 47. System.out.println("实现的接口 " + intes\[i\].getName()); 48. \} 49. \} 50. \} 【运行结果】: 实现的接口 Reflect.China (注意,以下几个例子,都会用到这个例子的Person类,所以为节省篇幅,此处不再粘贴Person的代码部分,只粘贴主类hello的代码) 【案例6】:取得其他类中的父类 **\[java\]** [view plain][] [copy][view plain] 1. class hello \{ 2. public static void main(String\[\] args) \{ 3. Class<?> demo = null; 4. try \{ 5. demo = Class.forName("Reflect.Person"); 6. \} catch (Exception e) \{ 7. e.printStackTrace(); 8. \} 9. //取得父类 10. Class<?> temp = demo.getSuperclass(); 11. System.out.println("继承的父类为: " + temp.getName()); 12. \} 13. \} 【运行结果】 继承的父类为: java.lang.Object 【案例7】:获得其他类中的全部构造函数 这个例子需要在程序开头添加import java.lang.reflect.\*; 然后将主类编写为: **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.Constructor; 2. 3. class hello \{ 4. public static void main(String\[\] args) \{ 5. Class<?> demo = null; 6. try \{ 7. demo = Class.forName("Reflect.Person"); 8. \} catch (Exception e) \{ 9. e.printStackTrace(); 10. \} 11. Constructor<?> cons\[\] = demo.getConstructors(); 12. for (int i = 0; i < cons.length; i++) \{ 13. System.out.println("构造方法: " + cons\[i\]); 14. \} 15. \} 16. \} 【运行结果】: 构造方法: public Reflect.Person() 构造方法: public Reflect.Person(java.lang.String) 【案例8】接下来让我们取得其他类的全部属性吧,最后我讲这些整理在一起,也就是通过class取得一个类的全部框架 **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.Modifier; 2. 3. class hello \{ 4. public static void main(String\[\] args) \{ 5. Class<?> demo = null; 6. try \{ 7. demo = Class.forName("Reflect.Person"); 8. \} catch (Exception e) \{ 9. e.printStackTrace(); 10. \} 11. System.out.println("===============本类属性========================"); 12. // 取得本类的全部属性 13. Field\[\] field = demo.getDeclaredFields(); 14. for (int i = 0; i < field.length; i++) \{ 15. // 权限修饰符 16. int mo = field\[i\].getModifiers(); 17. String priv = Modifier.toString(mo); 18. // 属性类型 19. Class<?> type = field\[i\].getType(); 20. System.out.println(priv + " " + type.getName() + " " 21. + field\[i\].getName() + ";"); 22. \} 23. System.out.println("===============实现的接口或者父类的属性========================"); 24. // 取得实现的接口或者父类的属性 25. Field\[\] filed1 = demo.getFields(); 26. for (int j = 0; j < filed1.length; j++) \{ 27. // 权限修饰符 28. int mo = filed1\[j\].getModifiers(); 29. String priv = Modifier.toString(mo); 30. // 属性类型 31. Class<?> type = filed1\[j\].getType(); 32. System.out.println(priv + " " + type.getName() + " " 33. + filed1\[j\].getName() + ";"); 34. \} 35. \} 36. \} 【运行结果】: ===============本类属性======================== private java.lang.String sex; ===============实现的接口或者父类的属性======================== public static final java.lang.String name; public static final int age; 【案例9】其实还可以通过反射调用其他类中的方法: **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.Method; 2. 3. class hello \{ 4. public static void main(String\[\] args) \{ 5. Class<?> demo = null; 6. try \{ 7. demo = Class.forName("Reflect.Person"); 8. \} catch (Exception e) \{ 9. e.printStackTrace(); 10. \} 11. try \{ 12. //调用Person类中的sayChina方法 13. Method method = demo.getMethod("sayChina"); 14. method.invoke(demo.newInstance()); 15. //调用Person的sayHello方法 16. method = demo.getMethod("sayHello", String.class, int.class); 17. method.invoke(demo.newInstance(), "Rollen", 20); 18. 19. \} catch (Exception e) \{ 20. e.printStackTrace(); 21. \} 22. \} 23. \} 【运行结果】: hello ,china Rollen 20 【案例10】调用其他类的set和get方法 **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.Method; 2. 3. class hello \{ 4. public static void main(String\[\] args) \{ 5. Class<?> demo = null; 6. Object obj = null; 7. try \{ 8. demo = Class.forName("Reflect.Person"); 9. \} catch (Exception e) \{ 10. e.printStackTrace(); 11. \} 12. try \{ 13. obj = demo.newInstance(); 14. \} catch (Exception e) \{ 15. e.printStackTrace(); 16. \} 17. setter(obj, "Sex", "男", String.class); 18. getter(obj, "Sex"); 19. \} 20. 21. /\*\* 22. \* @param obj 操作的对象 23. \* @param att 操作的属性 24. \*/ 25. public static void getter(Object obj, String att) \{ 26. try \{ 27. Method method = obj.getClass().getMethod("get" + att); 28. System.out.println(method.invoke(obj)); 29. \} catch (Exception e) \{ 30. e.printStackTrace(); 31. \} 32. \} 33. 34. /\*\* 35. \* @param obj 操作的对象 36. \* @param att 操作的属性 37. \* @param value 设置的值 38. \* @param type 参数的属性 39. \*/ 40. public static void setter(Object obj, String att, Object value, Class<?> type) \{ 41. try \{ 42. Method method = obj.getClass().getMethod("set" + att, type); 43. method.invoke(obj, value); 44. \} catch (Exception e) \{ 45. e.printStackTrace(); 46. \} 47. \} 48. \}// end class 【运行结果】: 男 【案例11】通过反射操作属性 **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.Field; 2. 3. class hello \{ 4. public static void main(String\[\] args) throws Exception \{ 5. Class<?> demo = null; 6. Object obj = null; 7. 8. demo = Class.forName("Reflect.Person"); 9. obj = demo.newInstance(); 10. 11. Field field = demo.getDeclaredField("sex"); 12. field.setAccessible(true); 13. field.set(obj, "男"); 14. System.out.println(field.get(obj)); 15. \} 16. \}// end class 【案例12】通过反射取得并修改数组的信息: **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.\*; 2. 3. class hello \{ 4. public static void main(String\[\] args) \{ 5. int\[\] temp = \{ 1, 2, 3, 4, 5\}; 6. Class<?> demo = temp.getClass().getComponentType(); 7. System.out.println("数组类型: " + demo.getName()); 8. System.out.println("数组长度 " + Array.getLength(temp)); 9. System.out.println("数组的第一个元素: " + Array.get(temp, 0)); 10. Array.set(temp, 0, 100); 11. System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0)); 12. \} 13. \} 【运行结果】: 数组类型: int 数组长度 5 数组的第一个元素: 1 修改之后数组第一个元素为: 100 【案例13】通过反射修改数组大小 **\[java\]** [view plain][] [copy][view plain] 1. import java.lang.reflect.Array; 2. 3. class hello \{ 4. public static void main(String\[\] args) \{ 5. int\[\] temp = \{ 1, 2, 3, 4, 5, 6, 7, 8, 9\}; 6. int\[\] newTemp = (int\[\]) arrayInc(temp, 15); 7. print(newTemp); 8. System.out.println("====================="); 9. String\[\] atr = \{ "a", "b", "c"\}; 10. String\[\] str1 = (String\[\]) arrayInc(atr, 8); 11. print(str1); 12. \} 13. 14. /\*\* 15. \* 修改数组大小 16. \*/ 17. public static Object arrayInc(Object obj, int len) \{ 18. Class<?> arr = obj.getClass().getComponentType(); 19. Object newArr = Array.newInstance(arr, len); 20. int co = Array.getLength(obj); 21. System.arraycopy(obj, 0, newArr, 0, co); 22. return newArr; 23. \} 24. 25. /\*\* 26. \* 打印 27. \*/ 28. public static void print(Object obj) \{ 29. Class<?> c = obj.getClass(); 30. if (!c.isArray()) \{ 31. return; 32. \} 33. System.out.println("数组长度为: " + Array.getLength(obj)); 34. for (int i = 0; i < Array.getLength(obj); i++) \{ 35. System.out.print(Array.get(obj, i) + " "); 36. \} 37. \} 38. \} 【运行结果】: 数组长度为: 15 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 ===================== 数组长度为: 8 a b c null null null null null [view plain]: https://blog.csdn.net/qq_27093465/article/details/52254924# [bug]: http://blog.csdn.net/qq_27093465/article/details/51567110
相关 Java反射机制应用案例解析 Java反射机制是Java语言提供的一种允许程序在运行状态中了解类信息、动态调用方法以及获取对象属性值等能力的机制。 以下是一个简单的反射机制应用案例解析: 1. **创建 拼搏现实的明天。/ 2024年09月18日 09:12/ 0 赞/ 4 阅读
相关 Java反射机制实例解析 Java反射机制是Java语言提供的一种能力,允许程序在运行时检查类的信息(如方法、属性等)并动态调用这些信息。 下面是一个简单的实例解析: ```java // 创建一个 我就是我/ 2024年09月16日 21:51/ 0 赞/ 14 阅读
相关 Java反射机制深入解析 Java的反射机制是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息。以下是反射机制深入解析的关键点: 1. 类加载:当Java应用需要访问一个类时,Java虚拟机 亦凉/ 2024年09月15日 05:03/ 0 赞/ 7 阅读
相关 Java反射机制的应用案例解析 Java的反射机制允许我们在运行时动态地查看类的信息,操作对象等。以下是一个具体的应用案例解析: **案例:获取指定类的所有属性** 1. **使用反射创建Class对象* 缺乏、安全感/ 2024年09月13日 02:48/ 0 赞/ 11 阅读
相关 Java反射机制常见问题:示例解析 在Java编程中,反射机制是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息。然而,使用反射可能会遇到一些常见的问题。下面是一些示例来解析这些问题: 1. **安全 ゝ一世哀愁。/ 2024年09月13日 01:36/ 0 赞/ 20 阅读
相关 Java反射机制深入解析 Java的反射机制是一种强大的工具,它允许程序在运行时检查和修改类、对象及方法的信息。下面对Java反射机制进行深入解析: 1. **Class**:这是反射的主要对象类型, 忘是亡心i/ 2024年09月11日 19:57/ 0 赞/ 43 阅读
相关 Java反射机制滥用问题案例解析 在Java编程中,反射是一种强大的工具,它允许我们在运行时检查类、对象和方法的信息。然而,如果滥用反射,可能会导致性能下降,安全风险增加等问题。 以下是几个常见的滥用反射的案 拼搏现实的明天。/ 2024年09月06日 02:48/ 0 赞/ 23 阅读
相关 Java反射机制解析 首先在反射之前我们要先了解java类的整个加载机制:我们的.java源码文件通过编译之后会生成一个JVM可识别的二进制字节码.class文件,每一个类都会产生一个Class对象 - 日理万妓/ 2022年04月23日 12:36/ 0 赞/ 230 阅读
相关 java反射机制详细解析 (一)什么是反射机制? 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动 喜欢ヅ旅行/ 2021年09月15日 02:32/ 0 赞/ 325 阅读
还没有评论,来说两句吧...