0x01 前言

前面一章节的学习,学习到类如何获取类还有获取类的方法与调用类方法。
通过本章节即可学习到如何修改成员变量与调用类的构造方法。

0x01.1 目录结构

  1. # 目录结构
  2. ├── 反射
  3. └── java获取成员变量与构造函数信息4
  4. ├── Test.java (用来做测试的方法)
  5. ├── Person.java

0x01.2 例子-Person类(用于理解的)

  1. // 该类具体路径: 反射.java获取成员变量与构造函数信息4.Person
  2. package 反射.java获取成员变量与构造函数信息4;
  3. public class Person {
  4. public String name = "大狗";
  5. public int age;
  6. private String sex;
  7. private static final int height = 160;
  8. // 构造方法一
  9. public Person() {
  10. this.setName("二狗");
  11. this.setAge(18);
  12. this.setSex("男");
  13. System.out.println(" ");
  14. System.out.println("====================");
  15. System.out.println("公共的无参数构造方法被调用");
  16. }
  17. // 构造方法二
  18. public Person(String name) {
  19. this.setName(name);
  20. System.out.println(" ");
  21. System.out.println("====================");
  22. System.out.println("公共的带name参数的构造方法被调用");
  23. System.out.println("TA的名字: " + name);
  24. }
  25. // 构造方法三
  26. public Person(String name,int age) {
  27. this.setName(name);
  28. this.setAge(age);
  29. System.out.println(" ");
  30. System.out.println("====================");
  31. System.out.println("公共的带name参数与age参数的构造方法被调用");
  32. System.out.println("TA的名字: " + name);
  33. System.out.println("TA的年龄: " + age);
  34. }
  35. // 构造方法四
  36. private Person(String name, String sex) {
  37. this.setName(name);
  38. this.setSex(sex);
  39. System.out.println(" ");
  40. System.out.println("====================");
  41. System.out.println("私有的带name参数与sex参数的构造方法被调用");
  42. System.out.println("TA的名字: " + name);
  43. System.out.println("TA的性别: " + sex);
  44. }
  45. public void setName(String name) {
  46. this.name = name;
  47. }
  48. public void setAge(int age) {
  49. this.age = age;
  50. }
  51. private void setSex(String sex) {
  52. this.sex = sex;
  53. }
  54. }

0x02 获取当前类所有成员变量的信息

0x02.1 getFields()

  1. getFields() //获取的是所有的public的成员变量的信息,包括父类继承而来的
  1. // 例子1-获取Person类所有的public的成员变量的信息
  2. import java.lang.reflect.Field;
  3. public class Test {
  4. public static void main(String[] args) {
  5. try {
  6. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  7. // 通过类类型,创建该类对象
  8. Object pObject = p.newInstance();
  9. System.out.println(" ");
  10. System.out.println("====================================");
  11. Field[] fs = p.getFields();
  12. for (Field field : fs) {
  13. System.out.println(" ");
  14. System.out.println("成员变量的名称是: " + field.getName());
  15. System.out.println("成员变量的类型是: " + field.getType().getName());
  16. }
  17. System.out.println("====================================");
  18. System.out.println(" ");
  19. } catch (Exception e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }
  24. // 运行结果
  25. ====================
  26. 公共的无参数构造方法被调用
  27. ====================================
  28. 成员变量的名称是: name
  29. 成员变量的类型是: java.lang.String
  30. 成员变量的名称是: age
  31. 成员变量的类型是: int
  32. ====================================

0x02.2 getDeclaredFields()

  1. getDeclaredFields() 获取的是该类自己声明的成员变量的信息
  1. // 例子2-获取Person类自己声明的成员变量的信息
  2. package 反射.java获取成员变量与构造函数信息4;
  3. import java.lang.reflect.Field;
  4. public class Test {
  5. public static void main(String[] args) {
  6. try {
  7. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  8. // 通过类类型,创建该类对象
  9. Object pObject = p.newInstance();
  10. // 例子1:
  11. System.out.println(" ");
  12. System.out.println("====================================");
  13. Field[] fs = p.getDeclaredFields();
  14. for (Field field : fs) {
  15. System.out.println(" ");
  16. System.out.println("成员变量的名称是: " + field.getName());
  17. System.out.println("成员变量的类型是: " + field.getType().getName());
  18. }
  19. System.out.println("====================================");
  20. System.out.println(" ");
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. // 运行结果
  27. ====================
  28. 公共的无参数构造方法被调用
  29. ====================================
  30. 成员变量的名称是: name
  31. 成员变量的类型是: java.lang.String
  32. 成员变量的名称是: age
  33. 成员变量的类型是: int
  34. 成员变量的名称是: sex
  35. 成员变量的类型是: java.lang.String
  36. 成员变量的名称是: height
  37. 成员变量的类型是: int
  38. ====================================

0x03 获取当前类某个成员变量的信息

0x03.1 getField()

  1. getField() 获取的是当前类某个public的成员变量的信息,包括父类继承而来的
  1. // 例子1-获取公共name成员变量的值
  2. package 反射.java获取成员变量与构造函数信息4;
  3. import java.lang.reflect.Field;
  4. public class Test {
  5. public static void main(String[] args) {
  6. try {
  7. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  8. // 通过类类型,创建该类对象
  9. Object pObject = p.newInstance();
  10. // 获取公共name成员变量的信息
  11. Field nameField = p.getField("name");
  12. // 获取公共name成员变量的值
  13. System.out.println("");
  14. System.out.println(nameField.get(pObject));
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. }
  20. // 运行结果
  21. ====================
  22. 公共的无参数构造方法被调用
  23. 二狗

0x03.2 getDeclaredField()

  1. getDeclaredField() 获取的是当前类自己声明的某个成员变量的信息,不问访问权限
  1. // 例子2-修改与获取私有age成员变量的值
  2. package 反射.java获取成员变量与构造函数信息4;
  3. import java.lang.reflect.Field;
  4. public class Test {
  5. public static void main(String[] args) {
  6. try {
  7. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  8. // 通过类类型,创建该类对象
  9. Object pObject = p.newInstance();
  10. // 获取私有age成员变量的信息
  11. Field ageField = p.getDeclaredField("age");
  12. // 忽略访问修饰符的检查,这样就可以调用私有方法或是成员变量
  13. ageField.setAccessible(true);
  14. // 修改私有age成员变量的值
  15. ageField.set(pObject, 22);
  16. // 获取私有age成员变量的值
  17. System.out.println(" ");
  18. System.out.println(ageField.get(pObject));
  19. } catch (Exception e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }
  24. // 运行结果
  25. ====================
  26. 公共的无参数构造方法被调用
  27. 22
  1. // 例子3-修改私有的 static final关键字修饰的height成员变量
  2. package 反射.java获取成员变量与构造函数信息4;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Modifier;
  5. public class Test {
  6. public static void main(String[] args) {
  7. try {
  8. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  9. // 通过类类型,创建该类对象
  10. Object pObject = p.newInstance();
  11. // 当我们要修改static final关键字修饰的成员变量的时候
  12. // 我们需要修改Field中的modifiers数据域,清除代表final的那个bit
  13. // 这样才可以正常修改
  14. Field heightField = p.getDeclaredField("height");
  15. heightField.setAccessible(true);
  16. Field ms = heightField.getClass().getDeclaredField("modifiers");
  17. // 忽略访问修饰符的检查,这样就可以调用私有方法或是成员变量
  18. ms.setAccessible(true);
  19. ms.setInt(heightField, heightField.getModifiers() & ~Modifier.FINAL);
  20. // 修改私有的final关键字修饰的height成员变量的值
  21. heightField.set(pObject, 180);
  22. // 获取 static final关键字修饰的height成员变量的值
  23. System.out.println("");
  24. System.out.println(heightField.get(pObject));
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. // 运行结果
  31. ====================
  32. 公共的无参数构造方法被调用
  33. 180

0x04 获取当前类所有构造函数

0x04.1 getConstructors()

  1. getConstructors() 获取的是所有的public访问权限的构造函数
  1. // 例子-获取Person类所有的public访问权限的构造函数
  2. package 反射.java获取成员变量与构造函数信息4;
  3. import java.lang.reflect.Constructor;
  4. public class Test {
  5. public static void main(String[] args) {
  6. try {
  7. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  8. System.out.println(" ");
  9. System.out.println("====================================");
  10. Constructor[] pcs = p.getConstructors();
  11. for (Constructor constructor : pcs) {
  12. System.out.print(constructor.getName()+"(");
  13. //获取构造函数的参数列表--->得到的是参数列表的类类型
  14. Class[] paramTypes = constructor.getParameterTypes();
  15. for (Class class1 : paramTypes) {
  16. System.out.print(class1.getName()+",");
  17. }
  18. System.out.println(")");
  19. }
  20. System.out.println("====================================");
  21. System.out.println(" ");
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. // 运行结果
  28. ====================================
  29. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,int,)
  30. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,)
  31. 反射.java获取成员变量与构造函数信息4.Person()
  32. ====================================

0x04.2 getDeclaredConstructors()

  1. getDeclaredConstructors() 获取的是该类自己声明的所有构造函数
  1. // 获取Person类自己声明的所有构造函数
  2. package 反射.java获取成员变量与构造函数信息4;
  3. import java.lang.reflect.Constructor;
  4. public class Test {
  5. public static void main(String[] args) {
  6. try {
  7. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  8. System.out.println(" ");
  9. System.out.println("====================================");
  10. Constructor[] pcs = p.getDeclaredConstructors();
  11. for (Constructor constructor : pcs) {
  12. System.out.print(constructor.getName()+"(");
  13. //获取构造函数的参数列表--->得到的是参数列表的类类型
  14. Class[] paramTypes = constructor.getParameterTypes();
  15. for (Class class1 : paramTypes) {
  16. System.out.print(class1.getName()+",");
  17. }
  18. System.out.println(")");
  19. }
  20. System.out.println("====================================");
  21. System.out.println(" ");
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. // 运行结果
  28. ====================================
  29. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,java.lang.String,)
  30. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,int,)
  31. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,)
  32. 反射.java获取成员变量与构造函数信息4.Person()
  33. ====================================

0x05 获取当前类某个构造函数

0x05.1 注意

  1. 调用的是那个构造方法与自己传入 getConstructor() / getDeclaredConstructor() 的参数有关
  2. 例如-想调用的是公共构造方法 getConstructor()
  3. Person()类的构造方法一 那么直接传入 p.getConstructor()
  4. Person()类的构造方法二 那么直接传入 p.getConstructor(String.class)
  5. Person()类的构造方法三 那么直接传入 p.getConstructor(String.class, int.class)
  6. 例如-想调用的是私有构造方法 getDeclaredConstructor()
  7. Person()类的构造方法四 那么直接传入
  8. Constructor test = p.getDeclaredConstructor(String.class, String.class);
  9. test.setAccessible(true);

0x05.2 getConstructor()

  1. getConstructor() 获取的是当前类某个public访问权限的构造函数,包括父类继承而来的
  1. // 例子1: Person类-获取无参数的公共构造方法
  2. // 也就是获取 构造方法一
  3. package 反射.java获取成员变量与构造函数信息4;
  4. import java.lang.reflect.Constructor;
  5. public class Test {
  6. public static void main(String[] args) {
  7. try {
  8. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  9. System.out.println(" ");
  10. System.out.println("====================================");
  11. Constructor test = p.getConstructor();
  12. System.out.print(test.getName()+"(");
  13. //获取构造函数的参数列表--->得到的是参数列表的类类型
  14. Class[] paramTypes = test.getParameterTypes();
  15. for (Class class1 : paramTypes) {
  16. System.out.print(class1.getName()+",");
  17. }
  18. System.out.println(")");
  19. //通过构造器对象 newInstance 方法对对象进行初始化 有参数构造函数
  20. Object obj=test.newInstance();
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. // 运行结果
  27. ====================================
  28. 反射.java获取成员变量与构造函数信息4.Person()
  29. ====================
  30. 公共的无参数构造方法被调用
  1. // 例子2: Person类-获取有两个参数的公共构造方法
  2. // 也就是获取 构造方法三
  3. package 反射.java获取成员变量与构造函数信息4;
  4. import java.lang.reflect.Constructor;
  5. public class Test {
  6. public static void main(String[] args) {
  7. try {
  8. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  9. System.out.println(" ");
  10. System.out.println("====================================");
  11. Constructor test = p.getConstructor(String.class, int.class);
  12. System.out.print(test.getName()+"(");
  13. //获取构造函数的参数列表--->得到的是参数列表的类类型
  14. Class[] paramTypes = test.getParameterTypes();
  15. for (Class class1 : paramTypes) {
  16. System.out.print(class1.getName()+",");
  17. }
  18. System.out.println(")");
  19. //通过构造器对象 newInstance 方法对对象进行初始化 有参数构造函数
  20. Object obj=test.newInstance("神奇的我",12);
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. // 运行结果
  27. ====================================
  28. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,int,)
  29. ====================
  30. 公共的带name参数与age参数的构造方法被调用
  31. TA的名字: 神奇的我
  32. TA的年龄: 12

0x05.3 getDeclaredConstructor()

  1. getDeclaredConstructor() 获取的是当前类自己声明的某个构造函数,不问访问权限
  1. // 例子3: Person类-获取有两个参数的私有构造方法
  2. // 也就是获取 构造方法四
  3. package 反射.java获取成员变量与构造函数信息4;
  4. import java.lang.reflect.Constructor;
  5. public class Test {
  6. public static void main(String[] args) {
  7. try {
  8. Class p = Class.forName("反射.java获取成员变量与构造函数信息4.Person");
  9. System.out.println(" ");
  10. System.out.println("====================================");
  11. Constructor test = p.getDeclaredConstructor(String.class, String.class);
  12. test.setAccessible(true);
  13. System.out.print(test.getName()+"(");
  14. //获取构造函数的参数列表--->得到的是参数列表的类类型
  15. Class[] paramTypes = test.getParameterTypes();
  16. for (Class class1 : paramTypes) {
  17. System.out.print(class1.getName()+",");
  18. }
  19. System.out.println(")");
  20. //通过构造器对象 newInstance 方法对对象进行初始化 有参数构造函数
  21. Object obj=test.newInstance("哇哦","女");
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. // 运行结果
  28. ====================================
  29. 反射.java获取成员变量与构造函数信息4.Person(java.lang.String,java.lang.String,)
  30. ====================
  31. 私有的带name参数与sex参数的构造方法被调用
  32. TA的名字: 哇哦
  33. TA的性别: