聊一聊Java反射中的Field
博客专区 > trayvon 的博客 > 博客详情
聊一聊Java反射中的Field
trayvon 发表于7个月前
聊一聊Java反射中的Field
  • 发表于 7个月前
  • 阅读 23
  • 收藏 0
  • 点赞 0
  • 评论 0
摘要: 本文主要介绍Java反射包中的Field的常用接口的用法

简介

Java中一个重要的机制就是反射了,很多自动化的功能都是通过反射完成的,这对很多框架是非常重要的,因为很多框架就是做顶层抽象处理公用的逻辑,所以对于实现层的东西是不清楚的,有了反射机制,框架就可以在运行时获取到自己需要的实现层的一些信息,从而做更多的事情。

Java的的反射包java.lang.reflect中提供的最常用且重要的几个类就是Field、Method、Constructor这3个类了,这3个类提供的接口很类似,所以这里就先聊一聊Field这个类

实例

这里我们通过一个实例来说一下Field类中常用的接口的意义用法和一下注意事项。field代表的是字段,所以我们先来一个实体bean

public class FieldBean <T>{
    
    @FieldAnnotation(type="int",filedName="intField")
    @FieldId
    private int intField;
    
    @FieldAnnotation(type="String",filedName="stringField")
    private String stringField;
    
    @FieldAnnotation(type="char",filedName="charField")
    private char charField;
    
    @FieldAnnotation(type="double",filedName="doubleField")
    private double doubleField;
    
    @FieldAnnotation(type="long",filedName="longField")
    private long longField;
    
    @FieldAnnotation(type="short",filedName="shortField")
    private short shortField;
    
    @FieldAnnotation(type="byte",filedName="byteField")
    private byte byteField;
    
    @FieldAnnotation(type="float",filedName="floatField")
    private float floatField;
    
    public int publicField;
    
    public static int publicStaticField;
    
    public final static int publicFinalStaticField = 0;
    
    private T objectField;

    public int getIntField() {
        return intField;
    }

    public void setIntField(int intField) {
        this.intField = intField;
    }

    public String getStringField() {
        return stringField;
    }

    public void setStringField(String stringField) {
        this.stringField = stringField;
    }

    public char getCharField() {
        return charField;
    }

    public void setCharField(char charField) {
        this.charField = charField;
    }

    public double getDoubleField() {
        return doubleField;
    }

    public void setDoubleField(double doubleField) {
        this.doubleField = doubleField;
    }

    public long getLongField() {
        return longField;
    }

    public void setLongField(long longField) {
        this.longField = longField;
    }

    public short getShortField() {
        return shortField;
    }

    public void setShortField(short shortField) {
        this.shortField = shortField;
    }

    public byte getByteField() {
        return byteField;
    }

    public void setByteField(byte byteField) {
        this.byteField = byteField;
    }

    public float getFloatField() {
        return floatField;
    }

    public void setFloatField(float floatField) {
        this.floatField = floatField;
    }

    public int getPublicField() {
        return publicField;
    }

    public void setPublicField(int publicField) {
        this.publicField = publicField;
    }

    public static int getPublicStaticField() {
        return publicStaticField;
    }

    public static void setPublicStaticField(int publicStaticField) {
        FieldBean.publicStaticField = publicStaticField;
    }

    public T getObjectField() {
        return objectField;
    }

    public void setObjectField(T objectField) {
        this.objectField = objectField;
    }

    public static int getPublicfinalstaticfield() {
        return publicFinalStaticField;
    }

    @Override
    public String toString() {
        return "FieldBean [intField=" + intField + ", stringField=" + stringField + ", charField=" + charField
                + ", doubleField=" + doubleField + ", longField=" + longField + ", shortField=" + shortField
                + ", byteField=" + byteField + ", floatField=" + floatField + ", publicField=" + publicField
                + ", objectField=" + objectField + "]";
    }
    
    public static <E> FieldBean<E> getDefaultFieldBean(E object){
        FieldBean<E> bean = new FieldBean<E>();
        bean.byteField = Byte.MAX_VALUE;
        bean.charField = 'c';
        bean.doubleField = Double.MIN_NORMAL;
        bean.floatField = Float.MAX_VALUE;
        bean.intField = Integer.MAX_VALUE;
        bean.longField = Long.MAX_VALUE;
        bean.shortField = Short.MAX_VALUE;
        bean.stringField = "string";
        bean.objectField = object;
        return bean;
    }

}

上面的实体bean使用到的2个注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldAnnotation {
    
    public String type();
    
    public String filedName();

}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldId {

}

主类:

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Date;

public class FieldStart {
    
    public static void main(String[] args) {
        Date date = new Date(System.currentTimeMillis());
        FieldBean<Date> bean = FieldBean.getDefaultFieldBean(date);
        System.out.println(bean);
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        printFieldInfo(fields);
        dealIntField(clazz,bean);
        dealGetGenericType(clazz);
    }
    
    private static void dealGetGenericType(Class<?> clazz){
        try {
            Field field = clazz.getDeclaredField("objectField");
            Type type = field.getGenericType();
            System.out.println(type);
            System.out.println(type instanceof TypeVariable);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
    
    private static void dealIntField(Class<?> clazz,FieldBean<Date> bean){
        try {
            Field intField = clazz.getDeclaredField("intField");
            Annotation[] annotations = intField.getAnnotations();
            for (int i = 0; i < annotations.length; i++) {
                System.out.println(annotations[i]);
            }
            FieldAnnotation fieldAnnotation = intField.getAnnotation(FieldAnnotation.class);
            System.out.println(fieldAnnotation.type()+"  "+fieldAnnotation.filedName());
            intField.setAccessible(true);
            int intValue = intField.getInt(bean);
            System.out.println(intValue);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    
    private static void printFieldInfo(Field[] fields){
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            System.out.println("name:"+field.getName());
            System.out.println("modify:"+Modifier.toString(field.getModifiers()));
            System.out.println("declaringClass:"+field.getDeclaringClass());
            System.out.println("genericType:"+field.getGenericType());
            System.out.println("type:"+field.getType());
        }
    }

}

下面以FieldBean中的intField为例来介绍一下各个接口:

@FieldAnnotation(type="int",filedName="intField")
@FieldId
private int intField;

使用最多的接口getName()接口,这个接口就是获取字段的名字,那么上面这个字段代表的Field实例上调用getName()接口,获取的值就是intField。

另外2个常用的接口就是getAnnotations()和getAnnotation(Class)了,getAnnotations()是获取字段上的所有注解实例,同样如上面的字段代表的Field调用getAnnotations()获取到的就是包含了FieldAnnotation和FieldId的数组。调用getAnnotation(FieldAnnotation.class)获取的就是FieldAnnotation的实例,调用getAnnotation(FieldId.class)就是获取的FieldId实例。

注解的确是非常方便的,所以很多框架就通过注解来避免xml配置和强制继承,进而避免和实现层的强耦合,也避免了侵入到实现层的代码中。例如:在类上的注解@Controller,在参数上的注解@Param,在字段上的注解@JSONField,@Id,@Resource,@Autowired等。

获取值,Field类提供了getInt(Object),getLong(Object)等基本类型的方法来获取object实例对应的值,也提供了getObject(Object)接口。 注意:获取值的接口是有访问权限的可以通过setAccessible(true);来避免权限检查。

getDeclaringClass()接口是获取字段所在的类Class,上面的intField字段所代表的Filed实例上调用getDeclaringClass()获取的就是FieldBean.class

getType()接口是获取字段的类型,上面的intField字段所代表的Filed实例上调用getType()获取到的值就是int.class

getModifiers()接口是获取字段的修饰符,例如下面的intField字段所代表的Filed实例上调用getModifiers()方法获取的就是public static final,注意:getModifiers()获取到的是一个int类型的可以通过Modifier.toString(field.getModifiers()))转换一下。

public final static int publicFinalStaticField = 0;

getGenericType()接口是获取字段的泛型类型,例如下面的intField字段所代表的Filed实例上调用getGenericType()获取到的就是:T,实际的类型是TypeVariable

private T objectField;

总结

  1. Field可以通过getName获取字段名称
  2. Field可以通过getAnnotations()和getAnnotation(Class)获取字段注解
  3. Field可以通过getInt(Object)获取指定对象字段的值
  4. 通过setAccessible(true)可以访问私有字段
标签: Java反射 Field
共有 人打赏支持
粉丝 12
博文 91
码字总数 140014
作品 1
×
trayvon
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: