1. 一个需求引出反射

第20章 反射 - 图1

  1. @SuppressWarnings({"all"})
  2. public class ReflectionQuestion {
  3. public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
  4. //根据配置文件 re.properties 指定信息, 创建Cat对象并调用方法hi
  5. //老韩回忆
  6. //传统的方式 new 对象 -》 调用方法
  7. // Cat cat = new Cat();
  8. // cat.hi(); ===> cat.cry() 修改源码.
  9. //我们尝试做一做 -> 明白反射
  10. //1. 使用Properties 类, 可以读写配置文件
  11. Properties properties = new Properties();
  12. properties.load(new FileInputStream("src\\re.properties"));
  13. String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat"
  14. String methodName = properties.get("method").toString();//"hi"
  15. System.out.println("classfullpath=" + classfullpath);
  16. System.out.println("method=" + methodName);
  17. //2. 创建对象 , 传统的方法,行不通 =》 反射机制
  18. //new classfullpath();
  19. //3. 使用反射机制解决
  20. //(1) 加载类, 返回Class类型的对象cls
  21. Class cls = Class.forName(classfullpath);
  22. //(2) 通过 cls 得到你加载的类 com.hspedu.Cat 的对象实例
  23. Object o = cls.newInstance();
  24. System.out.println("o的运行类型=" + o.getClass()); //运行类型
  25. //(3) 通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象
  26. // 即:在反射中,可以把方法视为对象(万物皆对象)
  27. Method method1 = cls.getMethod(methodName);
  28. //(4) 通过method1 调用方法: 即通过方法对象来实现调用方法
  29. System.out.println("=============================");
  30. method1.invoke(o); //传统方法 对象.方法() , 反射机制 方法.invoke(对象)
  31. }
  32. }

2. java反射机制

Java Reflection

第20章 反射 - 图2

Java 反射机制原理示意图!!!

第20章 反射 - 图3

Java 反射机制可以完成

第20章 反射 - 图4

反射相关的主要类

第20章 反射 - 图5

  1. public class Reflection01 {
  2. public static void main(String[] args) throws Exception {
  3. //1. 使用Properties 类, 可以读写配置文件
  4. Properties properties = new Properties();
  5. properties.load(new FileInputStream("src\\re.properties"));
  6. String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat"
  7. String methodName = properties.get("method").toString();//"hi"
  8. //2. 使用反射机制解决
  9. //(1) 加载类, 返回Class类型的对象cls
  10. Class cls = Class.forName(classfullpath);
  11. //(2) 通过 cls 得到你加载的类 com.hspedu.Cat 的对象实例
  12. Object o = cls.newInstance();
  13. System.out.println("o的运行类型=" + o.getClass()); //运行类型
  14. //(3) 通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象
  15. // 即:在反射中,可以把方法视为对象(万物皆对象)
  16. Method method1 = cls.getMethod(methodName);
  17. //(4) 通过method1 调用方法: 即通过方法对象来实现调用方法
  18. System.out.println("=============================");
  19. method1.invoke(o); //传统方法 对象.方法() , 反射机制 方法.invoke(对象)
  20. //java.lang.reflect.Field: 代表类的成员变量, Field对象表示某个类的成员变量
  21. //得到name字段
  22. //getField不能得到私有的属性
  23. Field nameField = cls.getField("age"); //
  24. System.out.println(nameField.get(o)); // 传统写法 对象.成员变量 , 反射 : 成员变量对象.get(对象)
  25. //java.lang.reflect.Constructor: 代表类的构造方法, Constructor对象表示构造器
  26. Constructor constructor = cls.getConstructor(); //()中可以指定构造器参数类型, 返回无参构造器
  27. System.out.println(constructor);//Cat()
  28. Constructor constructor2 = cls.getConstructor(String.class); //这里老师传入的 String.class 就是String类的Class对象
  29. System.out.println(constructor2);//Cat(String name)
  30. }
  31. }

反射优点和缺点

第20章 反射 - 图6

  1. public class Reflection02 {
  2. public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
  3. //Field
  4. //Method
  5. //Constructor
  6. m1();
  7. m2();
  8. m3();
  9. }
  10. //传统方法来调用hi
  11. public static void m1() {
  12. Cat cat = new Cat();
  13. long start = System.currentTimeMillis();
  14. for (int i = 0; i < 90; i++) {
  15. cat.hi();
  16. }
  17. long end = System.currentTimeMillis();
  18. System.out.println("m1() 耗时=" + (end - start));
  19. }
  20. //反射机制调用方法hi
  21. public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
  22. Class cls = Class.forName("com.hspedu.Cat");
  23. Object o = cls.newInstance();
  24. Method hi = cls.getMethod("hi");
  25. long start = System.currentTimeMillis();
  26. for (int i = 0; i < 900000000; i++) {
  27. hi.invoke(o);//反射调用方法
  28. }
  29. long end = System.currentTimeMillis();
  30. System.out.println("m2() 耗时=" + (end - start));
  31. }
  32. //反射调用优化 + 关闭访问检查
  33. public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
  34. Class cls = Class.forName("com.hspedu.Cat");
  35. Object o = cls.newInstance();
  36. Method hi = cls.getMethod("hi");
  37. hi.setAccessible(true);//在反射调用方法时,取消访问检查
  38. long start = System.currentTimeMillis();
  39. for (int i = 0; i < 900000000; i++) {
  40. hi.invoke(o);//反射调用方法
  41. }
  42. long end = System.currentTimeMillis();
  43. System.out.println("m3() 耗时=" + (end - start));
  44. }
  45. }

反射调用优化-关闭访问检查

第20章 反射 - 图7

第20章 反射 - 图8

3. Class类

基本介绍

第20章 反射 - 图9

第20章 反射 - 图10

  1. public class Class01 {
  2. public static void main(String[] args) throws ClassNotFoundException {
  3. //看看Class类图
  4. //1. Class也是类,因此也继承Object类
  5. //Class
  6. //2. Class类对象不是new出来的,而是系统创建的
  7. //(1) 传统new对象
  8. /* ClassLoader类
  9. public Class<?> loadClass(String name) throws ClassNotFoundException {
  10. return loadClass(name, false);
  11. }
  12. */
  13. //Cat cat = new Cat();
  14. //(2) 反射方式, 刚才老师没有debug到 ClassLoader类的 loadClass, 原因是,我没有注销Cat cat = new Cat();
  15. /*
  16. ClassLoader类, 仍然是通过 ClassLoader类加载Cat类的 Class对象
  17. public Class<?> loadClass(String name) throws ClassNotFoundException {
  18. return loadClass(name, false);
  19. }
  20. */
  21. Class cls1 = Class.forName("com.hspedu.Cat");
  22. //3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  23. Class cls2 = Class.forName("com.hspedu.Cat");
  24. System.out.println(cls1.hashCode());
  25. System.out.println(cls2.hashCode());
  26. Class cls3 = Class.forName("com.hspedu.Dog");
  27. System.out.println(cls3.hashCode());
  28. }
  29. }

Class 类的常用方法

第20章 反射 - 图11

  1. public class Class01 {
  2. public static void main(String[] args) throws ClassNotFoundException {
  3. //看看Class类图
  4. //1. Class也是类,因此也继承Object类
  5. //Class
  6. //2. Class类对象不是new出来的,而是系统创建的
  7. //(1) 传统new对象
  8. /* ClassLoader类
  9. public Class<?> loadClass(String name) throws ClassNotFoundException {
  10. return loadClass(name, false);
  11. }
  12. */
  13. //Cat cat = new Cat();
  14. //(2) 反射方式, 刚才老师没有debug到 ClassLoader类的 loadClass, 原因是,我没有注销Cat cat = new Cat();
  15. /*
  16. ClassLoader类, 仍然是通过 ClassLoader类加载Cat类的 Class对象
  17. public Class<?> loadClass(String name) throws ClassNotFoundException {
  18. return loadClass(name, false);
  19. }
  20. */
  21. Class cls1 = Class.forName("com.hspedu.Cat");
  22. //3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  23. Class cls2 = Class.forName("com.hspedu.Cat");
  24. System.out.println(cls1.hashCode());
  25. System.out.println(cls2.hashCode());
  26. Class cls3 = Class.forName("com.hspedu.Dog");
  27. System.out.println(cls3.hashCode());
  28. }
  29. }

应用实例: Class02.java

  1. public class Class002 {
  2. public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
  3. //找到car类
  4. String classAllPath = "com.hspedu.Car";
  5. //获取Class对象
  6. Class<?> cls = Class.forName(classAllPath);
  7. //输出cls
  8. System.out.println(cls); //显示是哪个类的Class对象
  9. System.out.println(cls.getName()); //返回全类名
  10. System.out.println(cls.getClass()); //返回运行类型
  11. System.out.println(cls.getPackage().getName());//获取包名
  12. Object o = cls.getDeclaredConstructor().newInstance();//java9以后 创建对象实例
  13. //Car car = (Car) cls.getDeclaredConstructor().newInstance();//java9以后 创建对象实例
  14. //System.out.println(car);
  15. //通过反射获取属性brand
  16. Field brand = cls.getField("brand");
  17. System.out.println(brand.get(o));
  18. //赋值
  19. brand.set(o,"奔驰");
  20. System.out.println(brand.get(o));
  21. //获取所有字段
  22. Field[] fields = cls.getFields();
  23. for (Field o1 :fields) {
  24. System.out.println(o1.getName() + "-" + o1.get(o));
  25. }
  26. }
  27. }

4. 获取Class类对象

第20章 反射 - 图12

第20章 反射 - 图13

第20章 反射 - 图14

不同阶段理解

第20章 反射 - 图15

  1. public class GetClass_ {
  2. public static void main(String[] args) throws ClassNotFoundException {
  3. //1. Class.forName
  4. String classAllPath = "com.hspedu.Car"; //通过读取配置文件获取
  5. Class<?> cls1 = Class.forName(classAllPath);
  6. System.out.println(cls1);
  7. //2. 类名.class , 应用场景: 用于参数传递
  8. Class cls2 = Car.class;
  9. System.out.println(cls2);
  10. //3. 对象.getClass(), 应用场景,有对象实例
  11. Car car = new Car();
  12. Class cls3 = car.getClass();
  13. System.out.println(cls3);
  14. //4. 通过类加载器【4种】来获取到类的Class对象
  15. //(1)先得到类加载器 car
  16. ClassLoader classLoader = car.getClass().getClassLoader();
  17. //(2)通过类加载器得到Class对象
  18. Class cls4 = classLoader.loadClass(classAllPath);
  19. System.out.println(cls4);
  20. //cls1 , cls2 , cls3 , cls4 其实是同一个对象
  21. System.out.println(cls1.hashCode());
  22. System.out.println(cls2.hashCode());
  23. System.out.println(cls3.hashCode());
  24. System.out.println(cls4.hashCode());
  25. //5. 基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象
  26. Class<Integer> integerClass = int.class;
  27. Class<Character> characterClass = char.class;
  28. Class<Boolean> booleanClass = boolean.class;
  29. System.out.println(integerClass);//int
  30. //6. 基本数据类型对应的包装类,可以通过 .TYPE 得到Class类对象
  31. Class<Integer> type1 = Integer.TYPE;
  32. Class<Character> type2 = Character.TYPE; //其它包装类BOOLEAN, DOUBLE, LONG,BYTE等待
  33. System.out.println(type1);
  34. System.out.println(integerClass.hashCode());//?
  35. System.out.println(type1.hashCode());//?
  36. }
  37. }

5. 哪些类型有Class对象

如下类型有 Class 对象

第20章 反射 - 图16

应用实例

  1. public class AllTypeClass {
  2. public static void main(String[] args) {
  3. Class<String> cls1 = String.class;//外部类
  4. Class<Serializable> cls2 = Serializable.class;//接口
  5. Class<Integer[]> cls3 = Integer[].class;//数组
  6. Class<float[][]> cls4 = float[][].class;//二维数组
  7. Class<Deprecated> cls5 = Deprecated.class;//注解
  8. //枚举
  9. Class<Thread.State> cls6 = Thread.State.class;
  10. Class<Long> cls7 = long.class;//基本数据类型
  11. Class<Void> cls8 = void.class;//void数据类型
  12. Class<Class> cls9 = Class.class;//
  13. System.out.println(cls1);
  14. System.out.println(cls2);
  15. System.out.println(cls3);
  16. System.out.println(cls4);
  17. System.out.println(cls5);
  18. System.out.println(cls6);
  19. System.out.println(cls7);
  20. System.out.println(cls8);
  21. System.out.println(cls9);
  22. }
  23. }

6. 类加载

基本说明

第20章 反射 - 图17

类加载时机

第20章 反射 - 图18

类加载过程图

第20章 反射 - 图19

  1. 验证: 安全校验
  2. 准备: 静态变量 分配内存 默认初始化
  3. 解析: 虚拟机把常量池中的符号引用替换为直接引用

类加载各阶段完成任务

第20章 反射 - 图20

加载阶段

第20章 反射 - 图21

连接阶段-验证

第20章 反射 - 图22

连接阶段-准备

第20章 反射 - 图23

  1. public class ClassLoad02 {
  2. public static void main(String[] args) {
  3. }
  4. }
  5. class A {
  6. //属性-成员变量-字段
  7. //老韩分析类加载的链接阶段-准备 属性是如何处理
  8. //1. n1 是实例属性, 不是静态变量,因此在准备阶段,是不会分配内存
  9. //2. n2 是静态变量,分配内存 n2 是默认初始化 0 ,而不是20
  10. //3. n3 是static final 是常量, 他和静态变量不一样, 因为一旦赋值就不变 n3 = 30
  11. public int n1 = 10;
  12. public static int n2 = 20;
  13. public static final int n3 = 30;
  14. }

连接阶段-解析

第20章 反射 - 图24

  1. 符号引用: 相当于相对引用
  2. 直接引用: 相当于绝对引用(在内存中被分配地址) --- JVM机操作

Initialization(初始化)

第20章 反射 - 图25

  1. public class ClassLoad03 {
  2. public static void main(String[] args) throws ClassNotFoundException {
  3. //老韩分析
  4. //1. 加载B类,并生成 B的class对象
  5. //2. 链接 num = 0
  6. //3. 初始化阶段
  7. // 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
  8. /*
  9. clinit() {
  10. System.out.println("B 静态代码块被执行");
  11. //num = 300;
  12. num = 100;
  13. }
  14. 合并: num = 100
  15. */
  16. //new B();//类加载 4.会输出构造器
  17. //System.out.println(B.num);//100, 如果直接使用类的静态属性,也会导致类的加载,但是不会调用构造器
  18. //看看加载类的时候,是有同步机制控制
  19. /*
  20. protected Class<?> loadClass(String name, boolean resolve)
  21. throws ClassNotFoundException
  22. {
  23. //正因为有这个机制,才能保证某个类在内存中, 只有一份Class对象
  24. synchronized (getClassLoadingLock(name)) {
  25. //....
  26. }
  27. }
  28. */
  29. B b = new B();
  30. }
  31. }
  32. class B {
  33. static {
  34. System.out.println("B 静态代码块被执行");
  35. num = 300;
  36. }
  37. static int num = 100;
  38. public B() {//构造器
  39. System.out.println("B() 构造器被执行");
  40. }
  41. }

7. 通过反射获取类的结构信息

第一组: java.lang.Class 类

第20章 反射 - 图26

第二组: java.lang.reflect.Field 类

第20章 反射 - 图27

第三组: java.lang.reflect.Method 类

第20章 反射 - 图28

第四组: java.lang.reflect.Constructor 类

第20章 反射 - 图29

  1. public class ReflectionUtils {
  2. public static void main(String[] args) {
  3. }
  4. @Test
  5. public void api_02() throws ClassNotFoundException, NoSuchMethodException {
  6. //得到Class对象
  7. Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
  8. //getDeclaredFields:获取本类中所有属性
  9. //规定 说明: 默认修饰符 是0 , public 是1 ,private 是 2 ,protected 是 4 , static 是 8 ,final 是 16
  10. Field[] declaredFields = personCls.getDeclaredFields();
  11. for (Field declaredField : declaredFields) {
  12. System.out.println("本类中所有属性=" + declaredField.getName()
  13. + " 该属性的修饰符值=" + declaredField.getModifiers()
  14. + " 该属性的类型=" + declaredField.getType());
  15. }
  16. //getDeclaredMethods:获取本类中所有方法
  17. Method[] declaredMethods = personCls.getDeclaredMethods();
  18. for (Method declaredMethod : declaredMethods) {
  19. System.out.println("本类中所有方法=" + declaredMethod.getName()
  20. + " 该方法的访问修饰符值=" + declaredMethod.getModifiers()
  21. + " 该方法返回类型" + declaredMethod.getReturnType());
  22. //输出当前这个方法的形参数组情况
  23. Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
  24. for (Class<?> parameterType : parameterTypes) {
  25. System.out.println("该方法的形参类型=" + parameterType);
  26. }
  27. }
  28. //getDeclaredConstructors:获取本类中所有构造器
  29. Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
  30. for (Constructor<?> declaredConstructor : declaredConstructors) {
  31. System.out.println("====================");
  32. System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里老师只是输出名
  33. Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
  34. for (Class<?> parameterType : parameterTypes) {
  35. System.out.println("该构造器的形参类型=" + parameterType);
  36. }
  37. }
  38. }
  39. //第一组方法API
  40. @Test
  41. public void api_01() throws ClassNotFoundException, NoSuchMethodException {
  42. //得到Class对象
  43. Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
  44. //getName:获取全类名
  45. System.out.println(personCls.getName());//com.hspedu.reflection.Person
  46. //getSimpleName:获取简单类名
  47. System.out.println(personCls.getSimpleName());//Person
  48. //getFields:获取所有public修饰的属性,包含本类以及父类的
  49. Field[] fields = personCls.getFields();
  50. for (Field field : fields) {//增强for
  51. System.out.println("本类以及父类的属性=" + field.getName());
  52. }
  53. //getDeclaredFields:获取本类中所有属性
  54. Field[] declaredFields = personCls.getDeclaredFields();
  55. for (Field declaredField : declaredFields) {
  56. System.out.println("本类中所有属性=" + declaredField.getName());
  57. }
  58. //getMethods:获取所有public修饰的方法,包含本类以及父类的
  59. Method[] methods = personCls.getMethods();
  60. for (Method method : methods) {
  61. System.out.println("本类以及父类的方法=" + method.getName());
  62. }
  63. //getDeclaredMethods:获取本类中所有方法
  64. Method[] declaredMethods = personCls.getDeclaredMethods();
  65. for (Method declaredMethod : declaredMethods) {
  66. System.out.println("本类中所有方法=" + declaredMethod.getName());
  67. }
  68. //getConstructors: 获取所有public修饰的构造器,包含本类
  69. Constructor<?>[] constructors = personCls.getConstructors();
  70. for (Constructor<?> constructor : constructors) {
  71. System.out.println("本类的构造器=" + constructor.getName());
  72. }
  73. //getDeclaredConstructors:获取本类中所有构造器
  74. Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
  75. for (Constructor<?> declaredConstructor : declaredConstructors) {
  76. System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里老师只是输出名
  77. }
  78. //getPackage:以Package形式返回 包信息
  79. System.out.println(personCls.getPackage());//com.hspedu.reflection
  80. //getSuperClass:以Class形式返回父类信息
  81. Class<?> superclass = personCls.getSuperclass();
  82. System.out.println("父类的class对象=" + superclass);//
  83. //getInterfaces:以Class[]形式返回接口信息
  84. Class<?>[] interfaces = personCls.getInterfaces();
  85. for (Class<?> anInterface : interfaces) {
  86. System.out.println("接口信息=" + anInterface);
  87. }
  88. //getAnnotations:以Annotation[] 形式返回注解信息
  89. Annotation[] annotations = personCls.getAnnotations();
  90. for (Annotation annotation : annotations) {
  91. System.out.println("注解信息=" + annotation);//注解
  92. }
  93. }
  94. }
  95. class A {
  96. public String hobby;
  97. public void hi() {
  98. }
  99. public A() {
  100. }
  101. public A(String name) {
  102. }
  103. }
  104. interface IA {
  105. }
  106. interface IB {
  107. }
  108. @Deprecated
  109. class Person extends A implements IA, IB {
  110. //属性
  111. public String name;
  112. protected static int age; // 4 + 8 = 12
  113. String job;
  114. private double sal;
  115. //构造器
  116. public Person() {
  117. }
  118. public Person(String name) {
  119. }
  120. //私有的
  121. private Person(String name, int age) {
  122. }
  123. //方法
  124. public void m1(String name, int age, double sal) {
  125. }
  126. protected String m2() {
  127. return null;
  128. }
  129. void m3() {
  130. }
  131. private void m4() {
  132. }
  133. }

8. 通过反射创建对象

第20章 反射 - 图30

实例

案例演示 com.hspedu.reflection ReflecCreateInstance.java

测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造

测试 2:通过调用某个特定构造器的方式,实现创建某类的对象

  1. public class ReflecCreateInstance {
  2. public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
  3. //1. 先获取到User类的Class对象
  4. Class<?> userClass = Class.forName("com.hspedu.reflection.User");
  5. //2. 通过public的无参构造器创建实例
  6. Object o = userClass.newInstance();
  7. System.out.println(o);
  8. //3. 通过public的有参构造器创建实例
  9. /*
  10. constructor 对象就是
  11. public User(String name) {//public的有参构造器
  12. this.name = name;
  13. }
  14. */
  15. //3.1 先得到对应构造器
  16. Constructor<?> constructor = userClass.getConstructor(String.class);
  17. //3.2 创建实例,并传入实参
  18. Object hsp = constructor.newInstance("hsp");
  19. System.out.println("hsp=" + hsp);
  20. //4. 通过非public的有参构造器创建实例
  21. //4.1 得到private的构造器对象
  22. Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
  23. //4.2 创建实例
  24. //暴破【暴力破解】 , 使用反射可以访问private构造器/方法/属性, 反射面前,都是纸老虎
  25. constructor1.setAccessible(true);
  26. Object user2 = constructor1.newInstance(100, "张三丰");
  27. System.out.println("user2=" + user2);
  28. }
  29. }
  30. class User { //User类
  31. private int age = 10;
  32. private String name = "韩顺平教育";
  33. public User() {//无参 public
  34. }
  35. public User(String name) {//public的有参构造器
  36. this.name = name;
  37. }
  38. private User(int age, String name) {//private 有参构造器
  39. this.age = age;
  40. this.name = name;
  41. }
  42. public String toString() {
  43. return "User [age=" + age + ", name=" + name + "]";
  44. }
  45. }

9. 通过反射访问类中的成员

访问属性

第20章 反射 - 图31

  1. public class ReflecAccessProperty {
  2. public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
  3. //1. 得到Student类对应的 Class对象
  4. Class<?> stuClass = Class.forName("com.hspedu.reflection.Student");
  5. //2. 创建对象
  6. Object o = stuClass.newInstance();//o 的运行类型就是Student
  7. System.out.println(o.getClass());//Student
  8. //3. 使用反射得到age 属性对象
  9. Field age = stuClass.getField("age");
  10. age.set(o, 88);//通过反射来操作属性
  11. System.out.println(o);//
  12. System.out.println(age.get(o));//返回age属性的值
  13. //4. 使用反射操作name 属性
  14. Field name = stuClass.getDeclaredField("name");
  15. //对name 进行暴破, 可以操作private 属性
  16. name.setAccessible(true);
  17. //name.set(o, "老韩");
  18. name.set(null, "老韩~");//因为name是static属性,因此 o 也可以写出null
  19. System.out.println(o);
  20. System.out.println(name.get(o)); //获取属性值
  21. System.out.println(name.get(null));//获取属性值, 要求name是static
  22. }
  23. }
  24. class Student {//类
  25. public int age;
  26. private static String name;
  27. public Student() {//构造器
  28. }
  29. public String toString() {
  30. return "Student [age=" + age + ", name=" + name + "]";
  31. }
  32. }

访问方法

public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {

        //1. 得到Boss类对应的Class对象
        Class<?> bossCls = Class.forName("com.hspedu.reflection.Boss");
        //2. 创建对象
        Object o = bossCls.newInstance();
        //3. 调用public的hi方法
        //Method hi = bossCls.getMethod("hi", String.class);//OK
        //3.1 得到hi方法对象
        Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK
        //3.2 调用
        hi.invoke(o, "韩顺平教育~");

        //4. 调用private static 方法
        //4.1 得到 say 方法对象
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2 因为say方法是private, 所以需要暴破,原理和前面讲的构造器和属性一样
        say.setAccessible(true);
        System.out.println(say.invoke(o, 100, "张三", '男'));
        //4.3 因为say方法是static的,还可以这样调用 ,可以传入null
        System.out.println(say.invoke(null, 200, "李四", '女'));

        //5. 在反射中,如果方法有返回值,统一返回Object , 但是他运行类型和方法定义的返回类型一致
        Object reVal = say.invoke(null, 300, "王五", '男');
        System.out.println("reVal 的运行类型=" + reVal.getClass());//String


        //在演示一个返回的案例
        Method m1 = bossCls.getDeclaredMethod("m1");
        Object reVal2 = m1.invoke(o);
        System.out.println("reVal2的运行类型=" + reVal2.getClass());//Monster


    }
}

class Monster {}
class Boss {//类
    public int age;
    private static String name;

    public Boss() {//构造器
    }

    public Monster m1() {
        return new Monster();
    }

    private static String say(int n, String s, char c) {//静态方法
        return n + " " + s + " " + c;
    }

    public void hi(String s) {//普通public方法
        System.out.println("hi " + s);
    }
}

10. 练习

第20章 反射 - 图32

public class Homework01 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        /**
         * 定义PrivateTest类,有私有name属性,并且属性值为hellokitty
         * 提供getName的公有方法
         * 创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值
         */
        //1. 得到 PrivateTest类对应的Class对象
        Class<PrivateTest> privateTestClass = PrivateTest.class;
        //2. 创建对象实例
        PrivateTest privateTestObj = privateTestClass.newInstance();
        //3. 得到name属性对象
        Field name = privateTestClass.getDeclaredField("name");//name属性是private
        //4. 暴破name
        name.setAccessible(true);
        name.set(privateTestObj, "天龙八部");
        //5. 得到getName方法对象
        Method getName = privateTestClass.getMethod("getName");
        //6. 因为getName() 是public,所有直接调用
        Object invoke = getName.invoke(privateTestObj);
        System.out.println("name属性值=" + invoke);//天龙八部

    }
}

class PrivateTest {
    private String name = "hellokitty";
    //默认无参构造器
    public String getName() {
        return name;
    }
}

第20章 反射 - 图33

public class Homework02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /**
         * 利用Class类的forName方法得到File类的class 对象
         * 在控制台打印File类的所有构造器
         * 通过newInstance的方法创建File对象,并创建E:\mynew.txt文件
         */
        //1. Class类的forName方法得到File类的class 对象
        Class<?> fileCls = Class.forName("java.io.File");
        //2. 得到所有的构造器
        Constructor<?>[] declaredConstructors = fileCls.getDeclaredConstructors();
        //遍历输出
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("File构造器=" + declaredConstructor);
        }
        //3. 指定的得到 public java.io.File(java.lang.String)
        Constructor<?> declaredConstructor = fileCls.getDeclaredConstructor(String.class);
        String fileAllPath = "e:\\mynew.txt";
        Object file = declaredConstructor.newInstance(fileAllPath);//创建File对象

        //4. 得到createNewFile 的方法对象
        Method createNewFile = fileCls.getMethod("createNewFile");
        createNewFile.invoke(file);//创建文件,调用的是 createNewFile
        //file的运行类型就是File
        System.out.println(file.getClass());
        System.out.println("创建文件成功" + fileAllPath);

    }
}