• Java 类之 java.lang.reflect.Field


    Java 类之 java.lang.reflect.Field

    一、概述

    1、java.lang.Class 类获取字段的方法

    获取全部公有字段(含继承的,不含私有的)

    1. getField(String name)
      • 获取该类及其父类指定名称的公有字段。
      • 如果字段不存在,则抛出 NoSuchFieldException 异常。
    2. getFields()
      • 获取该类及其父类中所有公有字段的数组。
      • 返回一个 Field 对象数组。

    获取本类的所有字段(不含继承的,含私有的)

    1. getDeclaredField(String name)
      • 获取该类中指定名称的任意访问权限的字段,包括私有字段。
      • 如果字段不存在,则抛出 NoSuchFieldException 异常。
    2. getDeclaredFields()
      • 获取该类中所有声明的字段,包括私有字段。
      • 返回一个 Field 对象数组。

    代码示例

    // 获取公有字段(含继承的,不含私有的)
    Field publicField = MyClass.class.getField("publicField");
    System.out.println("Public Field: " + publicField);
    
    // 获取所有公有字段(含继承的,不含私有的)
    Field[] publicFields = MyClass.class.getFields();
    System.out.println("All Public Fields: ");
    for (Field field : publicFields) {
        System.out.println(field);
    }
    
    // 获取本类的私有字段(不含继承的,含私有的)
    Field privateField = MyClass.class.getDeclaredField("privateField");
    System.out.println("Private Field: " + privateField);
    
    // 获取本类的所有字段(不含继承的,含私有的)
    Field[] allFields = MyClass.class.getDeclaredFields();
    System.out.println("All Fields: ");
    for (Field field : allFields) {
        System.out.println(field);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2、java.lang.reflect.Field 类简介

    java.lang.reflect.Field 类是 Java 反射机制中用于表示类的字段(成员变量)的类。它提供了一种在运行时获取和操作类的字段的方式。

    3、类定义信息

    public final class Field extends AccessibleObject implements Member
    
    • 1

    二、基本功能

    1、基本功能

    1. 获取字段对象:
      • Class.getField(String name): 返回一个 Field 对象,该对象反映了指定公有字段的类或接口。
      • Class.getDeclaredField(String name): 返回一个 Field 对象,该对象反映了指定声明字段的类或接口。
    2. 获取所有字段:
      • Class.getFields(): 返回一个包含某个类或接口的所有公有字段的数组。
      • Class.getDeclaredFields(): 返回一个包含某个类或接口的所有字段的数组,包括私有字段。
    3. 操作字段:
      • Field.get(Object obj): 返回指定对象上此 Field 表示的字段的值。
      • Field.set(Object obj, Object value): 将指定对象上此 Field 表示的字段设置为指定的新值。
    4. 字段信息获取:
      • Field.getName(): 返回字段的名称。
      • Field.getType(): 返回字段的类型(Class 对象)。
      • Field.getModifiers(): 返回表示字段修饰符的整数。
    5. 访问字段修饰符:
      • Modifier.toString(int modifiers): 将修饰符转换为字符串形式。
    6. 设置可访问性:
      • Field.setAccessible(boolean flag): 设置字段的可访问性。如果字段是私有的,需要设置为 true 才能访问。

    2、代码示例

    import java.lang.reflect.Field;
    
    public class FieldExample {
        public String publicField;
        private int privateField;
    
        public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
            FieldExample obj = new FieldExample();
    
            // 获取公有字段对象
            Field publicField = FieldExample.class.getField("publicField");
            System.out.println("Public Field: " + publicField);
    
            // 获取私有字段对象
            Field privateField = FieldExample.class.getDeclaredField("privateField");
            System.out.println("Private Field: " + privateField);
    
            // 获取字段的名称、类型和修饰符
            System.out.println("Field Name: " + publicField.getName());
            System.out.println("Field Type: " + publicField.getType());
            System.out.println("Field Modifiers: " + publicField.getModifiers());
    
            // 获取并设置公有字段值
            publicField.set(obj, "Hello, Public Field!");
            System.out.println("Public Field Value: " + publicField.get(obj));
    
            // 获取并设置私有字段值(需要设置可访问性)
            privateField.setAccessible(true);
            privateField.set(obj, 42);
            System.out.println("Private Field Value: " + privateField.get(obj));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    三、扩展

    1、关于注解的方法

    1. 获取指定类型的注解:
      • Annotation getAnnotation(Class annotationClass): 返回指定类型的注解对象,如果字段没有指定类型的注解,则返回 null。
    2. 获取所有注解:
      • Annotation[] getAnnotations(): 返回包含此元素上存在的所有注解的数组。
      • Annotation[] getDeclaredAnnotations(): 返回直接存在于此元素上的所有注解的数组,与继承的注解无关。
    3. 判断是否存在指定类型的注解:
      • boolean isAnnotationPresent(Class annotationClass): 如果指定类型的注解存在于此元素上,则返回 true。

    2、getAnnotations()getDeclaredAnnotations() 的区别

    getAnnotation 方法

    • 该方法用于获取指定类型的注解,如果该注解不存在于该字段上,则返回 null
    • 如果注解存在于该字段上,且是继承关系的,该方法会沿着继承链一直找到最终的注解
    • 这个方法也会考虑到注解的继承,即如果指定类型的注解不存在于当前字段上,但存在于该字段的父类或父接口上,也会被返回。

    getDeclaredAnnotation 方法

    • 该方法用于获取指定类型的注解,如果该注解不存在于该字段上,则返回 null
    • getAnnotation 不同的是,getDeclaredAnnotation 不会考虑继承关系,只会在当前字段上查找指定类型的注解

    3、其他注意点

    访问控制: 如果字段是私有的,确保在使用前调用 setAccessible(true) 方法,以便绕过访问控制检查。否则,在访问私有字段时可能会抛出 IllegalAccessException 异常。

    field.setAccessible(true);
    
    • 1

    静态字段: 如果操作的是静态字段,可以将对象设置为 null,而不需要创建实例。

    field.set(null, value); // 设置静态字段
    Object value = field.get(null); // 获取静态字段的值
    
    • 1
    • 2

    字段类型检查: 在设置字段值之前,最好进行类型检查,以确保所设置的值与字段的类型相匹配。否则,在运行时可能会抛出 IllegalArgumentException

    if (field.getType() == int.class) {
        field.setInt(object, 42);
    }
    
    • 1
    • 2
    • 3

    异常处理: 在使用反射操作字段时,要考虑可能抛出的异常,如 NoSuchFieldExceptionIllegalAccessException 等。适当地进行异常处理是很重要的。

    try {
        Field field = MyClass.class.getDeclaredField("fieldName");
        // 其他操作
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    性能影响: 反射操作相比直接访问字段的性能较差。如果性能是一个关键问题,考虑使用其他手段,如直接访问字段或者使用生成的代码(如使用字节码增强库)。

    字段注解: 如果你使用注解,注意使用 getAnnotationgetDeclaredAnnotation 方法时的细微差别,根据需求选择合适的方法。

  • 相关阅读:
    【go语言】方法
    Neo4j学习笔记(二) 查询语言
    现代对称密码
    python将视频抽帧的的多种方式
    蓝牙数据包协议解析
    给出32位有符号整数,将这个整数翻转
    运放如何产生三角波信号
    java字符串转数字
    小米6安装Ubuntu Touch系统也不是很难嘛
    从一个 issue 出发,带你玩图数据库 NebulaGraph 内核开发
  • 原文地址:https://blog.csdn.net/qq_29689343/article/details/134538678