Java反射(Field)(四)

简介: 日常开发中,我们可使用反射获取JavaBean的属性信息,而描述属性信息的就是Java Field,Field类位于java.lang.reflect包下。

前言

image (1).png
日常开发中,我们可使用反射获取JavaBean的属性信息,而描述属性信息的就是Java Field,Field类位于java.lang.reflect包下。

Field

Field类提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或这个类的实例字段。

/**
 * A {@code 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.
 *
 * <p>A {@code Field} permits widening conversions to occur during a get or
 * set access operation, but throws an {@code IllegalArgumentException} if a
 * narrowing conversion would occur.
 *
 * @see Member
 * @see java.lang.Class
 * @see java.lang.Class#getFields()
 * @see java.lang.Class#getField(String)
 * @see java.lang.Class#getDeclaredFields()
 * @see java.lang.Class#getDeclaredField(String)
 *
 * @author Kenneth Russell
 * @author Nakul Saraiya
 */
public final class Field extends AccessibleObject implements Member {
    // ...
}

getModifiers

以整数形式返回由此Field对象表示的字段的Java语言修饰符(例如private, final, static等)。

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    private String name;

    private Integer age;
    
}

public static void main(String[] args) throws Exception {
        Class<?> userClass = User.class;
        // private
        // private
        for (Field field : userClass.getDeclaredFields()) {
            System.out.println(Modifier.toString(field.getModifiers()));
        }
}

getType

  • 返回一个Class对象,它标识了此Field对象所表示字段的类型。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    private String name;

    private Integer age;
    
}

public static void main(String[] args) throws Exception {

        Class<?> userClass = User.class;
        
        for (Field field : userClass.getDeclaredFields()) {
            // class java.lang.String
            // class java.lang.Integer
            System.out.println(field.getType());
        }
}

getName

  • 返回此Field对象表示的字段的名称。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    private String name;

    private Integer age;
    
}

public static void main(String[] args) throws Exception {

        Class<?> userClass = User.class;

        for (Field field : userClass.getDeclaredFields()) {
            // name
            // age
            System.out.println(field.getName());
        }
}

set

将指定对象变量上此Field对象表示的字段设置为指定的新值。如果底层字段的类型为基本类型,则对新值进行自动拆装箱。那么就会有如下几种场景:

  • 如果底层字段是静态字段,则忽略指定对象变量,对象变量而且也可以为null。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    public static String name;

    private Integer age;

}

public static void main(String[] args) throws Exception {

        User user = new User();

        Field field = user.getClass().getField("name");

        field.set(null, "Duan");
        // User(age=null)
        System.out.println(user);

        // User(age=null)
        field.set(user, "Duan");
        System.out.println(user);

}
  • 如果底层字段是实例字段,如果指定对象变量为null,则该方法将抛出一个NPE,见代码片段2。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    public String name;

    public Integer age;

}

public static void main(String[] args) throws Exception {

        User user = new User();

        Field field = user.getClass().getField("name");

        // NullPointerException
        field.set(null, "Duan");
        System.out.println(user);
}
  • 如果指定对象变量不是声明底层字段的类或接口的实例,则该方法将抛出一个IllegalArgumentException。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    public String name;

    public Integer age;

}

    public static void main(String[] args) throws Exception {

        User user = new User();

        Field field = user.getClass().getField("name");

        // IllegalArgumentException
        field.set(new Object(), "Duan");
        System.out.println(user);
    }
  • 如果字段为final字段,则该方法将抛出一个IllegalAccessException,除非设置setAccessible,并且该字段是一个非静态字段。在通过程序的其他部分可以访问类的实例之前,只有使用空白final字段反序列化或重构类的实例期间,以这种方式设置final字段才有意义。在其他任何上下文中使用该方法都可能会有不可预知的结果,包括程序的其他部分继续使用该字段的原始值的情况。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    public final String name = "";

    public Integer age;

}

    public static void main(String[] args) throws Exception {

        User user = new User();

        Field field = user.getClass().getField("name");

        // IllegalArgumentException
        field.set(user, "Duan");
        System.out.println(user);
    }
  • 如果底层字段的类型为某一基本类型,则可以尝试使用解包转换将新值转换为基本类型的值。如果该尝试失败,则此方法将抛出一个IllegalArgumentException。
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class User {

    public String name;

    public int age;

}

public static void main(String[] args) throws Exception {

        User user = new User();

        Field field = user.getClass().getField("age");
    
        field.set(user, 28);
        // " java.lang.IllegalArgumentException: Can not set int field User.age to java.lang.Long
        field.set(user, 22L);
        System.out.println(user);

}

get

返回指定对象上此Field表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。get的几种场景,与set基本类似,此不在过多赘述。

常用方法

getType 获取属性声明时类型对象,返回class对象。
getGenericType 返回属性的Type类型,可以试试如果是泛型的返回。
getAnnotations 获得这个属性上所有的注解。
getName 获取属性声明时名字。
getModifiers 获取属性的修饰。
set 向obj对象的这个Field设置值。
get 取得obj对象这个Field上的值。
isSynthetic 判断这个属性是否是合成字段,判断此字段是否为合成字段,如果是则返回true; 否则返回false
isEnumConstant 判断这个属性是否是枚举类。
目录
相关文章
|
28天前
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
|
1月前
|
Java
Java的反射
Java的反射。
29 2
|
2月前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
37 0
[Java]反射
|
3月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
75 9
Java——反射&枚举
|
2月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
30 2
|
3月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
2月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
21 0
|
3月前
|
Java 程序员 编译器
Java的反射技术reflect
Java的反射技术允许程序在运行时动态加载和操作类,基于字节码文件构建中间语言代码,进而生成机器码在JVM上执行,实现了“一次编译,到处运行”。此技术虽需更多运行时间,但广泛应用于Spring框架的持续集成、动态配置及三大特性(IOC、DI、AOP)中,支持企业级应用的迭代升级和灵活配置管理,适用于集群部署与数据同步场景。
|
3月前
|
存储 安全 Java
扫盲java基础-反射(一)
扫盲java基础-反射(一)
|
3月前
|
Java
扫盲java基础-反射(二)
扫盲java基础-反射(二)