Java反射—Field类使用

妖狐艹你老母 2021-10-01 09:44 439阅读 0赞

Field作为反射中对应类或对象中的域或者叫做属性的操作类,除了我前一篇文章中的得到名字和类型等,Field的作用不限于此。

*上篇文章:Java反射-初探反射基础)(点击进入) *

Java SE 8的Docs这样说:A Field provides information about, and dynamic access to, a single field of a class or an interface. The reflected field may be a class (static) field or an instance field.

简单理解就是:我们可用通过Field类对类或对象的field进行动态操作。

  • 关于Field的一些方法:

































































返回值 名字和参数 作用
Object get(Object obj) 返回这个object对应field字段的Object
xxx getXXX(Object obj) 同上,不过XXX可以是Int,Char,Boolean等
void set(Object obj, Object value) 设置obj对象的调用方法的这个field的值为value
void setXXX(Object obj, XXX value) 设置特定类型值,例setInt(Object obj,int value)
Class getDeclaringClass() 返回定义中的Class对象
String getName() 得到名字的字符串
int getModifier() 返回一个修饰符的值
Class getType() 返回这个field的对象Class
void setAccessible(boolean flag) 设置是否允许set get
boolean isAccessible() 查看field是否允许set和get。

其他的可以去Java的官方文档去查看。https://docs.oracle.com/javase/8/docs/api/

  • 简单案例:

    1. package io.ilss.reflection;
    2. /**
    3. * className User
    4. * description User
    5. *
    6. * @author feng
    7. * @version 1.0
    8. * @date 2019-01-26 19:11
    9. */
    10. public class User {
    11. private String username;
    12. private String password;
    13. private int sex;
    14. public String address; //注意这个是public
    15. public User() {
    16. }
    17. public User(String username, String password) {
    18. this.username = username;
    19. this.password = password;
    20. }
    21. ...//getter setter method
    22. }
    23. package io.ilss.reflection;
    24. import java.lang.annotation.Annotation;
    25. import java.lang.reflect.Field;
    26. /**
    27. * className UserTest
    28. * description UserTest
    29. *
    30. * @author feng
    31. * @version 1.0
    32. * @date 2019-01-26 19:12
    33. */
    34. public class UserTest {
    35. public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    36. User user = new User("ilss", "ilss password");
    37. Class cls = user.getClass();
    38. //获取username名字的Field
    39. Field usernameField = cls.getDeclaredField("username");
    40. System.out.println(usernameField.toString());
    41. //获取user对象对应的username
    42. Object o = getSafe(usernameField, user);
    43. System.out.println("The username value of user is " + o);
    44. //获取基本数据类型
    45. user.setSex(1);
    46. Field sexField = cls.getDeclaredField("sex");
    47. sexField.setAccessible(true);
    48. sexField.setInt(user, 2);
    49. int sex = sexField.getInt(user);
    50. System.out.println("user sex : " + sex);
    51. //对user进行修改值 pubic不需要setAccessible
    52. Field addressField = cls.getDeclaredField("address");
    53. addressField.set(user, "ilss address");
    54. System.out.println("user address : " + user.getAddress());
  1. }
  2. public static Object getSafe(Field field, Object obj) {
  3. Object ret = null;
  4. try {
  5. if (field.isAccessible()) {
  6. ret = field.get(obj);
  7. } else {
  8. field.setAccessible(true);
  9. ret = field.get(obj);
  10. }
  11. } catch (IllegalAccessException e) {
  12. e.printStackTrace();
  13. }
  14. return ret;
  15. }
  16. }
  17. 需要说的点:
  18. * setAccessible方法。是Field继承自AccessibleObject类,AccessibleObjectFieldMethodConstuctor类的父类。简单理解意思就是 如果类型是private修饰的,你不可以直接访问,就需要设置访问权限为true.如果是public则不需要设置。
  19. * setget调用的时候都需要确保可以访问,不然如果不能访问抛出IllegalAccessException
  • 制作一个通用的toString(Object obj)方法

    package io.ilss.reflection;

    import java.lang.reflect.AccessibleObject;
    import java.lang.reflect.Array;
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    import java.util.ArrayList;

    /**

    • className ObjectAnalyzer
    • description ObjectAnalyzer
      *
    • @author feng
    • @version 1.0
    • @date 2019-01-26 19:34
      */
      public class ObjectAnalyzer {
      private ArrayList visited = new ArrayList<>();

      public String toString(Object obj) {

      1. //无效处理
      2. if (obj == null) {
      3. return "null";
      4. }
      5. //注意 如果不判断contains可能会出现无限递归调用。
      6. if (visited.contains(obj)) {
      7. return "...";
      8. }
      9. //将已经处理的做记录
      10. visited.add(obj);
      11. Class cls = obj.getClass();
      12. //如果为String类型就直接返回
      13. if (cls == String.class) {
      14. return (String) obj;
      15. }
      16. //是否数组
      17. if (cls.isArray()) {
      18. //用StringBuilder来append字符串
      19. StringBuilder r = new StringBuilder(cls.getComponentType() + "[]{");
      20. //利用relect包的Array操作类来便利
      21. for (int i = 0; i < Array.getLength(obj); i++) {
      22. if (i > 0) {
      23. r.append(",");
      24. }
      25. Object val = Array.get(obj, i);
      26. // getComponentType() 得到数组对象元素的类型
      27. // isPrimitive()是判断是否是基本数据类型
      28. if (cls.getComponentType().isPrimitive()) {
      29. r.append(val);
      30. } else {
      31. //不是基本数据类型就递归调用。
      32. r.append(toString(val));
      33. }
      34. }
      35. return r + "}";
      36. }
      1. StringBuilder ret = new StringBuilder(cls.getName());
      2. do {
      3. ret.append("[");
      4. Field[] fields = cls.getDeclaredFields();
      5. //对fields数组的所有访问权限设置为true
      6. AccessibleObject.setAccessible(fields, true);
      7. for (Field f : fields) {
      8. //只对非static参数处理
      9. if (!Modifier.isStatic(f.getModifiers())) {
      10. //如果不是第一个就加逗号
      11. if (!ret.toString().endsWith("[")) {
      12. ret.append(",");
      13. }
      14. ret.append(f.getName()).append("=");
      15. try {
      16. //对field的值进行获取
      17. Class t = f.getType();
      18. Object val = f.get(obj);
      19. //基本数据类型就直接append 不是就递归调用
      20. if (t.isPrimitive()) {
      21. ret.append(val);
      22. } else {
      23. ret.append(toString(val));
      24. }
      25. } catch (Exception e) {
      26. e.printStackTrace();
      27. }
      28. }
      29. }
      30. ret.append("]");
      31. //处理父类
      32. cls = cls.getSuperclass();
      33. }
      34. while (cls != null);
      35. return ret.toString();
      36. }
      37. @Override
      38. public String toString() {
      39. //利用自己调用toString(this)来实现自己的toString
      40. return this.toString(this);
      41. }
      42. }

      注意:

      里面有个Array类,是java.lang.reflect包下一个数组操作类。代码里的调用意思都不难理解。就不解释了

      • 调用类

        package io.ilss.reflection;

        import java.util.ArrayList;
        import java.util.List;

        /**

        • className ObjectAnalyzerTest
        • description ObjectAnalyzerTest
          *
        • @author feng
        • @version 1.0
        • @date 2019-01-26 19:30
          */
          public class ObjectAnalyzerTest {
          public static void main(String[] args) {

          1. List<Integer> squares = new ArrayList<>();
          2. for (int i = 0; i < 5; i++) {
          3. squares.add(i * i);
          4. }
          5. System.out.println(new ObjectAnalyzer().toString(squares));
          6. System.out.println(new ObjectAnalyzer().toString());
          7. User[] arr = new User[10];
          8. System.out.println(new ObjectAnalyzer().toString(arr));
          9. User user = new User("ilss", "ilss password");
          10. System.out.println(new ObjectAnalyzer().toString(user));

          }
          }

      相关代码的github:https://github.com/imyiren/java-base-ilss

发表评论

表情:
评论列表 (有 0 条评论,439人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java反射Field使用及说明

    Java反射之Field使用及说明 1、 什么是反射? 反射 的目的是为了能在运行期间得到对象的结构(包括成员变量,方法,构造方法等),并可以在允许的情况下访问这些

    相关 Java反射 Field详解

    Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 Field 成员变量的介绍 每个成员变量有类型和值