反射是什么

反射的作用用一句简单的话来讲就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少。

能够分析类能力的程序就叫做反射,简单来说就是可以对代码进行操作的代码。反射机制的功能极为强大,可以用来:

  • 在运行时分析类的能力
  • 在运行时查看对象
  • 实现通用的数组操作代码
  • 利用Method对象来实现方法

从获取Class类开始

在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。这个类的获取方式有以下三种:

  1. 使用Object类中的getClass()方法来返回一个Class类的实例

    1. User user;
    2. Class userClass = user.getClass();
  2. 我们可以使用Class类的getName()方法来获取包含包名在内的类名。同样的,在已知这个名字的情况下,我们可以使用静态方法forName()获得类名对应的Class对象

  1. Random generator = new Random();
  2. Class randomClass = generator.getClass();
  3. //className = "java.util.Random"
  4. String className = randomClass.getName();
  5. //第二种方式获取
  6. Class newRandomClass = Class.forName(className);
  1. 获得Class类对象的第三种方法很简单,如果T是任意的Java类型(或者void关键字),T.class将代表匹配的类对象。例如:
  1. Class randomClass = Random.class;
  2. Class intClass = int.class;
  3. Class doubleClass = Double[].class;

如果我们想要创建一个类的实例,可以使用newInstance()方法来动态创建:

  1. String s = "java.util.Random";
  2. Object m = Class.forName(s).newInstance();

构造函数的反射

获得构造函数的方法

  1. //根据指定参数获得public构造器
  2. Constructor getConstructor(Class[] params);
  3. //获得public的所有构造器
  4. Constructor[] getConstructors();
  5. //根据指定参数获得public和非public的构造器
  6. Constructor getDeclaredConstructor(Class[] params);
  7. //获得public的所有构造器
  8. Constructor[] getDeclaredConstructors();

看这些方法如何使用,先来个Student类供我们反射使用

  1. public class Student {
  2. private static String TAG = Student.class.getSimpleName();
  3. public int age;
  4. private String name;
  5. public Student() {
  6. age = 20;
  7. name = "小明";
  8. }
  9. public Student(int age, String name) {
  10. Log.e(TAG, "Student: " + "age " + age + " name " + name);
  11. }
  12. public void StudentA() {
  13. Log.e(TAG, "StudentA: ");
  14. }
  15. public void StudentA(int age) {
  16. Log.e(TAG, "StudentA: " + "age " + age);
  17. }
  18. public void StudentA(int age, String name) {
  19. Log.e(TAG, "StudentA: " + "age " + age + " name " + name);
  20. }
  21. }

利用反射分析类的能力

在java.lang.reflect包(反射库)中有三各类Field,MethodConstructor分别用于描述类的域,方法和构造器。这三个类都有一个叫做getName()的方法,用于返回项目的名称。Filed类有一个getType()方法,用于返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法。

这三个类还有一个叫做getModifiers()的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用情况。另外,还可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifiers()返回的整型数值。例如,可以使用Modifier类中的isPublic()isPrivate()isFinal()判断方法或构造器是否是public,private或final。我们需要做的全部工作就是调用Modifier类的相应方法,并对返回的整数数值进行分析,另外,还可以利用Modifier.toString()方法将修饰符打印出来。

Class类中的getFields()getMethods()getConstructors()方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的公有成员。Class类的getDeclareFieds()getDeclareMethods()getDeclareConstructors()方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。

下面我们来编写一个程序可以做到输入类名,然后打印出这个类的全部信息的作用:

  1. package com.reflect.test;
  2. import com.sun.org.apache.xpath.internal.operations.Mod;
  3. import java.io.File;
  4. import java.lang.reflect.Constructor;
  5. import java.lang.reflect.Field;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.Modifier;
  8. import java.util.Scanner;
  9. public class ReflectionTest {
  10. public static void main(String[] args) {
  11. String name;
  12. if(args.length > 0){
  13. name = args[0];
  14. }else{
  15. Scanner in = new Scanner(System.in);
  16. System.out.println("请输入类名:");
  17. name = in.next();
  18. }
  19. try{
  20. Class c1 = Class.forName(name);
  21. Class superclass = c1.getSuperclass();
  22. String modifiers = Modifier.toString(c1.getModifiers());
  23. if(modifiers.length() > 0){
  24. System.out.println(modifiers + " ");
  25. }
  26. System.out.println("class"+name);
  27. if(superclass != null && superclass != Object.class){
  28. System.out.println("extends"+superclass.getName());
  29. }
  30. System.out.println("\n{\n");
  31. printConstructors(c1);
  32. System.out.println();
  33. printMethods(c1);
  34. System.out.println();
  35. printFields(c1);
  36. System.out.println("}");
  37. }catch (ClassNotFoundException e){
  38. e.printStackTrace();
  39. }
  40. System.exit(0);
  41. }
  42. private static void printFields(Class c1) {
  43. Field[] fields = c1.getDeclaredFields();
  44. for(Field field : fields){
  45. Class type = field.getType();
  46. String name = field.getName();
  47. System.out.println(" ");
  48. String modifiers = Modifier.toString(field.getModifiers());
  49. if(modifiers.length() > 0){
  50. System.out.println(modifiers + " ");
  51. }
  52. System.out.println(type.getName() + " " + name + ";");
  53. }
  54. }
  55. private static void printMethods(Class c1) {
  56. Method[] methods = c1.getDeclaredMethods();
  57. for(Method method : methods){
  58. Class returnType = method.getReturnType();
  59. String name = method.getName();
  60. System.out.println(" ");
  61. String modifiers = Modifier.toString(method.getModifiers());
  62. if(modifiers.length() > 0){
  63. System.out.println(modifiers + " ");
  64. }
  65. System.out.println(returnType.getName()+" "+name+"(");
  66. Class[] paramTypes = method.getParameterTypes();
  67. for(int j = 0; j < paramTypes.length; j++){
  68. if(j > 0){
  69. System.out.println(",");
  70. }
  71. System.out.println(paramTypes[j].getName());
  72. }
  73. System.out.println(");");
  74. }
  75. }
  76. private static void printConstructors(Class c1) {
  77. Constructor[] constructors = c1.getDeclaredConstructors();
  78. for(Constructor constructor : constructors){
  79. String name = constructor.getName();
  80. System.out.println(" ");
  81. String modifiers = Modifier.toString(constructor.getModifiers());
  82. if(modifiers.length() > 0){
  83. System.out.println(modifiers + " ");
  84. }
  85. System.out.println(name + "(");
  86. Class[] paramTypes = constructor.getParameterTypes();
  87. for(int j = 0; j < paramTypes.length; j++){
  88. if(j > 0){
  89. System.out.println(",");
  90. }
  91. System.out.println(paramTypes[j].getName());
  92. }
  93. System.out.println(");");
  94. }
  95. }
  96. }

输入java.long.Double

回显:

  1. 请输入类名:
  2. java.lang.Double
  3. public final
  4. Disconnected from the target VM, address: '127.0.0.1:51190', transport: 'socket'
  5. classjava.lang.Double
  6. extendsjava.lang.Number
  7. {
  8. public
  9. java.lang.Double(
  10. double
  11. );
  12. public
  13. java.lang.Double(
  14. java.lang.String
  15. );
  16. public
  17. boolean equals(
  18. java.lang.Object
  19. );
  20. public static
  21. java.lang.String toString(
  22. double
  23. );
  24. public
  25. java.lang.String toString(
  26. );
  27. public
  28. int hashCode(
  29. );
  30. public static
  31. int hashCode(
  32. double
  33. );
  34. public static
  35. double min(
  36. double
  37. ,
  38. double
  39. );
  40. public static
  41. double max(
  42. double
  43. ,
  44. double
  45. );
  46. public static native
  47. long doubleToRawLongBits(
  48. double
  49. );
  50. public static
  51. long doubleToLongBits(
  52. double
  53. );
  54. public static native
  55. double longBitsToDouble(
  56. long
  57. );
  58. public volatile
  59. int compareTo(
  60. java.lang.Object
  61. );
  62. public
  63. int compareTo(
  64. java.lang.Double
  65. );
  66. public
  67. byte byteValue(
  68. );
  69. public
  70. short shortValue(
  71. );
  72. public
  73. int intValue(
  74. );
  75. public
  76. long longValue(
  77. );
  78. public
  79. float floatValue(
  80. );
  81. public
  82. double doubleValue(
  83. );
  84. public static
  85. java.lang.Double valueOf(
  86. java.lang.String
  87. );
  88. public static
  89. java.lang.Double valueOf(
  90. double
  91. );
  92. public static
  93. java.lang.String toHexString(
  94. double
  95. );
  96. public static
  97. int compare(
  98. double
  99. ,
  100. double
  101. );
  102. public static
  103. boolean isNaN(
  104. double
  105. );
  106. public
  107. boolean isNaN(
  108. );
  109. public static
  110. boolean isFinite(
  111. double
  112. );
  113. public static
  114. boolean isInfinite(
  115. double
  116. );
  117. public
  118. boolean isInfinite(
  119. );
  120. public static
  121. double sum(
  122. double
  123. ,
  124. double
  125. );
  126. public static
  127. double parseDouble(
  128. java.lang.String
  129. );
  130. public static final
  131. double POSITIVE_INFINITY;
  132. public static final
  133. double NEGATIVE_INFINITY;
  134. public static final
  135. double NaN;
  136. public static final
  137. double MAX_VALUE;
  138. public static final
  139. double MIN_NORMAL;
  140. public static final
  141. double MIN_VALUE;
  142. public static final
  143. int MAX_EXPONENT;
  144. public static final
  145. int MIN_EXPONENT;
  146. public static final
  147. int SIZE;
  148. public static final
  149. int BYTES;
  150. public static final
  151. java.lang.Class TYPE;
  152. private final
  153. double value;
  154. private static final
  155. long serialVersionUID;
  156. }
  157. Process finished with exit code 0

不积跬步无以至千里

思维导图

扩展阅读:

https://blog.csdn.net/zhangqiluGrubby/article/details/60874013

https://www.daidingkang.cc/2017/07/18/java-reflection-annotations/

https://www.javazhiyin.com/17014.html

https://www.javazhiyin.com/17008.html

Java复习总结——详细理解Java反射机制的更多相关文章

  1. Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

    一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...

  2. 【Java】「深入理解Java虚拟机」学习笔记(1) - Java语言发展趋势

    0.前言 从这篇随笔开始记录Java虚拟机的内容,以前只是对Java的应用,聚焦的是业务,了解的只是语言层面,现在想深入学习一下. 对JVM的学习肯定不是看一遍书就能掌握的,在今后的学习和实践中如果有 ...

  3. Java提高篇之理解java的三大特性——继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  4. 【转】java提高篇(二)-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

  5. Java语法基础学习DayNineteen(反射机制)

    一.Refection定义 1.概述 Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性 ...

  6. Android(java)学习笔记106-2:反射机制

    1.反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

  7. Android(java)学习笔记46:反射机制

    1. 反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称 ...

  8. Java语法基础学习DayTwenty(反射机制续)

    一.Java动态代理 1.代理设计模式的原理 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上. 2. ...

  9. Java 干货之深入理解Java泛型

    一般的类和方法,只能使用具体的类型,要么是基本类型,要么是自定义的类.如果要编写可以应用多中类型的代码,这种刻板的限制对代码得束缚会就会很大. ---<Thinking in Java> ...

随机推荐

  1. C# foreach内部原理

    我们知道使用foreach的一个要求是对象必须继承自IEnumerable接口 这样才可以进行迭代 那内部是怎么实现的呢 这个时候会将对应的foreach语句转换为一个while循环 并且通过Move ...

  2. 【学亮开讲】Oracle内外连接查询20181119

    --内连接查询 --需求:查询显示业主编号.业主名称.业主类型名称 select os.id 业主编号,os.name 业主名称,ot.name 业主类型名称 from t_owners os,t_o ...

  3. vue-resources&axios

    vue-resource vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应. vue-resource特点: 体积小 vue-re ...

  4. JavaList addAll removeAll

    List<String>list1=new ArrayList<>(); list1.add("a"); list1.add("b"); ...

  5. javascript深入浅出——学习笔记(六种数据类型和隐式转换)

    在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容

  6. vue-axios的application/x-www-form-urlencod的post请求无法解析参数

    vue-axios的post会先将对象转为json然后再根据headers的设置再转一次格式,可以将参数先用qs.stringify()转一次再传输

  7. 10分钟让你的代码更加pythonic

    参考: https://blog.csdn.net/g8433373/article/details/80709116

  8. python学习笔记(12)--程序设计方法学

    计算思维: 逻辑思维:推演和演绎 实证思维:实验和验证,引力波->实验 计算思维:设计和构造,计算机为代表,汉诺塔递归. 计算思维特征 抽象和自动化,抽象问题的计算过程,利用计算机自动化求解. ...

  9. 在页面中有overflow-y:auto属性的div,当出现滚动条,点击返回顶部按钮,内容回这个div最顶部

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Yii2后台管理系统常规单据模块最佳实践

    后台管理系统的常规单据通常包括数据,页面,功能:其中数据,页面,功能又可以细分如下: 分类  二级分类  主要内容  注意事项  例如 数据 数据库迁移脚本  用于数据表生成及转态回滚 1.是否需要增 ...