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 判断这个属性是否是枚举类。
目录
相关文章
|
10天前
|
Java
【专栏】Java中的反射机制与应用实例
【4月更文挑战第27天】本文探讨了Java反射机制,该机制允许程序在运行时获取类信息、动态创建对象、调用方法和访问属性。反射通过Class、Constructor、Method和Field类实现。文中列举了反射的应用场景,如动态创建对象、调用方法、访问属性和处理注解,并提供了相关实例代码演示。
|
1天前
|
Java C++
Java反射的简单使用
Java反射的简单使用
11 3
|
1天前
|
SQL 存储 Java
【Java反射详解】
【Java反射详解】
6 1
|
5天前
|
Java
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识。入坑JAVA因它的面向对象特性、平台无关性、强大的标准库和活跃的社区支持。
19 2
|
8天前
|
Java 测试技术
滚雪球学Java(24):Java反射
【4月更文挑战第13天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
16 0
滚雪球学Java(24):Java反射
|
13天前
|
Java
Java 反射
Java 反射
|
13天前
|
设计模式 Java 索引
由反射引出的Java动态代理与静态代理
由反射引出的Java动态代理与静态代理
15 0
|
13天前
|
存储 Java Shell
深入剖析Java中的反射,由浅入深,层层剥离!
深入剖析Java中的反射,由浅入深,层层剥离!
14 1
|
15天前
|
Java API Spring
Java基础教程(13)-Java中的反射和动态代理
【4月更文挑战第13天】Java反射机制允许程序在运行时获取类的信息并调用其方法。Class类是基础,提供获取类属性和方法的能力。通过Class对象,可以操作实例字段和方法,如getField、getDeclaredField等。动态代理是Java提供的创建接口实例的机制,其中JDK动态代理需目标类实现接口,而Cglib则可代理未实现接口的类。动态代理涉及Proxy和InvocationHandler接口。
|
18天前
|
监控 Java 开发者
掌握 Java 反射和动态代理
【4月更文挑战第19天】Java反射和动态代理提供强大功能和灵活性。反射允许运行时检查和操作类,获取类信息、动态调用方法,但可能带来性能损失和降低代码可读性。动态代理则用于创建代理对象,实现透明性和横切关注点分离,常用于日志、权限检查等。两者结合能实现更复杂功能。掌握这些技术能提升代码的灵活性和可扩展性,但也需注意性能和可读性。通过学习和实践,能更好地构建高效软件系统。