红色标注为当前重点

image.png

反射机制概述: 动态语言的特性、通过对象查看类的内部信息 -> 运行时可调整自身结构。

image.png
image.png
image.png

反射能做的事?

image.png

java中类本身也是对象,因为所有类都是 java.lang.Class类的对象。

image.png

反射与权限修饰符疑问 ? : 反射(能不能调用的问题)、类的封装性(建不建议调用的问题)

“new或反射来实例化” 的疑问?(是否需要动态特性的问题)

image.png

反射的案例

下列文件放置于com.xj.java包下。
代码逻辑:
从test1(),test2(),test3(),test4()依次介绍Class实例创建,使用Class实例来创建目标运行时实例,体会反射的动态性,反射(Class实例)来获取任何结构信息
RejectionTest.javaPerson.javaMyInterface.javaMyAnnotation.java

RejectionTest.java

  1. package com.xj.java;
  2. import org.junit.jupiter.api.Test;
  3. import java.lang.reflect.*;
  4. import java.util.Random;
  5. /**
  6. * @author jia
  7. * @create 2021-12-21 7:43 下午
  8. */
  9. public class RejectionTest {
  10. @Test
  11. public static Class test1() throws Exception {
  12. /**
  13. * Class实例对应着一个运行时类(含void、注解、数组等任意结构),体现java万事万物皆对象。
  14. * 4种方法获得该Class实例
  15. * */
  16. // 方法1
  17. Class clazz = Person.class;
  18. // 方法2
  19. Class clazz2 = new Person().getClass();
  20. // 方式3 全类名 (最常使用)
  21. Class clazz3 = Class.forName("com.xj.java.Person");
  22. // 方式4 类的加载器 (了解)
  23. ClassLoader classLoader = RejectionTest.class.getClassLoader();
  24. Class clazz4 = classLoader.loadClass("com.xj.java.Person");
  25. // 多种方式,其实是同一个运行时类
  26. System.out.println(clazz == clazz2);
  27. System.out.println(clazz == clazz3);
  28. System.out.println(clazz == clazz4);
  29. System.out.println(clazz3);
  30. return clazz3;
  31. }
  32. @Test
  33. public Person test2() throws Exception {
  34. /**
  35. * 使用反射(Class实例)来创建运行时实例。
  36. * 注意:必须提供空参构造器,一般为public权限。
  37. * */
  38. Class clazz = test1();
  39. // Person obj = (Person) clazz.newInstance();
  40. Person obj = (Person) clazz.getDeclaredConstructor().newInstance();
  41. System.out.println(obj);
  42. return obj;
  43. }
  44. @Test
  45. public void test3() throws Exception{
  46. /**
  47. * 体会反射的动态性
  48. * */
  49. int t = new Random().nextInt(2);
  50. String classPath = null;
  51. switch (t){
  52. case 0:
  53. classPath = "com.xj.java.Person";
  54. break;
  55. case 1:
  56. classPath = "java.lang.Object";
  57. break;
  58. }
  59. Object obj = getInstance(classPath);
  60. System.out.println(obj);
  61. }
  62. public Object getInstance(String classPath) throws Exception {
  63. Class clazz = Class.forName(classPath);
  64. // Object obj = clazz.newInstance();
  65. Object obj = clazz.getDeclaredConstructor().newInstance();
  66. return obj;
  67. }
  68. @Test
  69. public void test4() throws Exception{
  70. /**
  71. 反射(Class实例)来获取任何类信息,包括注解等
  72. */
  73. // Class实例
  74. Class clazz = Class.forName("com.xj.java.Person");
  75. // 获得空参构造器结构
  76. Constructor declaredConstructor = clazz.getDeclaredConstructor();// 获取构造器,一般获取空参构造器
  77. declaredConstructor.setAccessible(true);
  78. // 利用构造器结构来实例化对象
  79. Person person = (Person) declaredConstructor.newInstance();
  80. // 调用具体实例的方法
  81. Method show = clazz.getDeclaredMethod("show", String.class);// 方法名,形参列表
  82. show.setAccessible(true); // 无视权限限制
  83. Method info = clazz.getDeclaredMethod("info");// 静态方法
  84. info.setAccessible(true);
  85. Object showreturnval = show.invoke(person, "中国");// 具体实例,方法形参
  86. Object inforeturnval = info.invoke(person); // 静态方法(此处方法无形参), 方法无返回值依然要可接收返回值,则此处返回null
  87. System.out.println("show方法返回值:" + showreturnval);
  88. System.out.println("info静态方法的空返回值:" + inforeturnval);
  89. // 修改和访问具体实例额的属性
  90. Field name = clazz.getDeclaredField("name");
  91. name.setAccessible(true);
  92. name.set(person,"good man");
  93. System.out.println("对象的name属性:" + name.get(person));
  94. // 访问注解信息
  95. MyAnnotation myAnnotation = (MyAnnotation)clazz.getDeclaredAnnotation(MyAnnotation.class);// 获取注解
  96. System.out.println("注解的value信息:" + myAnnotation.value());
  97. // 获取包结构
  98. Package pack = clazz.getPackage();
  99. System.out.println("包名:"+pack);
  100. // 获取接口结构
  101. Class[] interfaces = clazz.getInterfaces();
  102. for (Class v : interfaces){
  103. System.out.println(v);
  104. }
  105. // 获得父类
  106. Class superClazz = clazz.getSuperclass();
  107. System.out.println("父类:" +superClazz.getName());
  108. // 获得带泛型的父类
  109. Type genericSuperclass1 = clazz.getGenericSuperclass();
  110. System.out.println("带泛型的父类:" + genericSuperclass1.getTypeName());
  111. // 获取泛型信息(包括泛型类、泛型接口)
  112. Type genericSuperclass = clazz.getGenericSuperclass();
  113. ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
  114. Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
  115. for (Type type : actualTypeArguments){
  116. System.out.println("类的泛型信息:" + type.getTypeName());
  117. }
  118. Type[] genericInterfaces = clazz.getGenericInterfaces();
  119. for (Type type : genericInterfaces){
  120. System.out.println("接口的泛型信息:" + type.getTypeName());
  121. }
  122. }
  123. }

国籍:中国,名字:null,年龄:0 我是静态方法 show方法返回值:中国 info静态方法的空返回值:null 对象的name属性:good man 注解的value信息:my annotation for class 包名:package com.xj.java interface java.lang.Comparable interface com.xj.java.MyInterface 父类:com.xj.java.Creater 带泛型的父类:com.xj.java.Creater 类的泛型信息:java.lang.String 接口的泛型信息:java.lang.Comparable 接口的泛型信息:com.xj.java.MyInterface

Person.java

  1. package com.xj.java;
  2. import java.io.Serializable;
  3. /**
  4. * @author jia
  5. * @create 2021-12-21 7:42 下午
  6. */
  7. class Creater<T> implements Serializable {
  8. private char gender;
  9. public double weight;
  10. private void breath(){
  11. System.out.println("生物呼吸");
  12. }
  13. private void eat(){
  14. System.out.println("生物进食");
  15. }
  16. }
  17. @MyAnnotation(value="my annotation for class")
  18. public class Person extends Creater<String> implements Comparable<String>,MyInterface{
  19. public String name;
  20. private int age;
  21. public Person(){};
  22. private Person(String name) {
  23. this.name = name;
  24. }
  25. public Person(String name, int age) {
  26. this.name = name;
  27. this.age = age;
  28. }
  29. @MyAnnotation(value="my annotation for show method")
  30. @Override
  31. public String show(String nation){
  32. System.out.println("国籍:" + nation + ",名字:" + this.name + ",年龄:" + this.age);
  33. return nation;
  34. }
  35. @MyAnnotation(value="my annotation for info static method")
  36. private static void info(){
  37. System.out.println("我是静态方法");
  38. }
  39. @Override
  40. public int compareTo(String o) {
  41. return 0;
  42. }
  43. }

MyAnnotation.java

  1. package com.xj.java;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. import static java.lang.annotation.ElementType.*;
  6. /**
  7. * @author jia
  8. * @create 2021-12-22 10:49 上午
  9. */
  10. @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
  11. @Retention(RetentionPolicy.RUNTIME) // 持续到RUNTIME
  12. public @interface MyAnnotation {
  13. String value() default "hello";
  14. }

MyInterface.java

  1. package com.xj.java;
  2. /**
  3. * @author jia
  4. * @create 2021-12-22 10:51 上午
  5. */
  6. public interface MyInterface {
  7. public String show(String nation);
  8. }