Field的使用

概述

Field是一个类,位于Java.lang.reflect包下,在Java反射中Field用于获取某个类的属性或该属性的属性值。

获取Field类对象

下面的四种获取Field类都将使用下面这个实体类

//Person.java
public class Person{  
	public String name;  
	private Integer age;  
	private String sex;  
//省略所有属性的set、get方法  
}

Class.getDeclaredField(String name)

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)

//通过Class.getDeclaredField(String name)获取类或接口的指定已声明字段。  
Field f1 = person.getClass().getDeclaredField("name"); 

System.out.println("-----Class.getDeclaredField(String name)用法-------");  
System.out.println(f1);

/*
-----Class.getDeclaredField(String name)用法-------  
public java.lang.String com.mao.test.Person.name
*/

Class.getDeclaredFields()

返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)

//通过Class.getDeclaredFields()获取类或接口的指定已声明字段。  
Field[] f2 = person.getClass().getDeclaredFields();  
for(Field field:f2)  
{  
    System.out.println(field);  
}  
/*
public java.lang.String com.mao.test.Person.name  
private java.lang.Integer com.mao.test.Person.age  
private java.lang.String com.mao.test.Person.sex
*/

Class.getField(String name)

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

//通过Class.getField(String name)返回一个类或接口的指定公共成员字段,私有成员报错。  
Field f3=person.getClass().getField("name");  
System.out.println(f3);

/*
public java.lang.String com.mao.test.Person.name
*/

Class.getFields()

返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问公共字段。


//通过Class.getField(),返回 Class 对象所表示的类或接口的所有可访问公共字段。  
Field []f4 = person.getClass().getFields();  
for(Field fields:f4)  
{  
    //因为只有name属性为共有,因此只能遍历出name属性  
    System.out.println(fields);  
}
/*
public java.lang.String com.mao.test.Person.name
*/

Field的主要方法

Field类中最常用的是get(Object obj)和set(Object obj, Object value)这两个方法,所以这两个方法是最重要的

getType(): 获取属性声明时类型对象(返回class对象)

getGenericType() : 返回属性声的Type类型

getName() : 获取属性声明时名字

getAnnotations() : 获得这个属性上所有的注释

getModifiers() : 获取属性的修饰

isEnumConstant() : 判断这个属性是否是枚举类

isSynthetic() : 判断这个属性是否是 复合类

get(Object obj) : 取得obj对象这个Field上的值

set(Object obj, Object value) : 向obj对象的这个Field设置新值value

下面便将比较重要的给代码演示了,其他的便不演示了

getType()

获取属性声明时类型对象(返回class对象)

Java Field.getType()获取属性声明时类型对象,它标识了此Field对象所表示字段的声明类型。

getType()返回的是Class对象,如果属性是一个泛型,从getType()只能得到这个属性的接口类型。

具体的代码可以看getGenericType()中的使用,在这里将getGenericType和getType()对比学习

getGenericType()

getType(): 获取属性声明时类型对象(返回class对象)

getGenericType() : 返回属性声明时的Type类型

getType() 和 getGenericType()的区别

  1. 首先是返回的类型不一样,一个是Class对象一个是Type接口。

  2. 如果属性是一个泛型,从getType()只能得到这个属性的接口类型。但从getGenericType()还能得到这个泛型的参数类型。

  3. getGenericType()如果当前属性有签名属性类型就返回,否则就返回 Field.getType()

public class FieldSpy<T>{
    public boolean[][] b = {{true, true}, {false, false}};
    public String name = "test";
    public Integer integer = 23;
    public T type;
    public static final String CLASS_NAME = "com.abc.test.Test";
    public static void main(String[] args) {
        try {
            // 返回的是一个类
            Class<?> aClass = Class.forName(CLASS_NAME);
            Field[] fields = aClass.getFields();
            for (Field field : fields) {
                System.out.println("Field:" + field.getName());
                System.out.println("Type:\n " + field.getType().getCanonicalName());
                System.out.println("GenericType:\n " + field.getGenericType().toString());
                System.out.println("\n");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

运行结果

Field:b         //二维的布尔值数组
Type:
  boolean[][]
GenericType:
  class [[Z

Field:name 
Type:
  java.lang.String
GenericType:
  class java.lang.String

Field:integer 
Type:
  java.lang.Integer
GenericType:
  class java.lang.Integer

Field:type         //泛型 T 类型,运行时被擦除为 Object
Type:
  java.lang.Object
GenericType:
  T

Field:CLASS_NAME 
Type:
  java.lang.String
GenericType:
  class java.lang.String

getName()

获取属性声明时名字

class A {
    int fild = 3;
    //这个是staticFild的注解
    static int staticFild = 4;
}
public class Test  {
    public static void main(String[] args) throws NoSuchFieldException {
        Field field = A.class.getDeclaredField("fild");
        String name = field.getName();
        System.out.println(name);//fild
    }
}

getAnnotations()

获得这个属性上所有的注释



getModifiers()

获取属性的修饰



isEnumConstant()

判断这个属性是否是枚举类



isSynthetic()

判断这个属性是否是 复合类



get(Object obj)

取得obj对象这个Field上的值

  1. 如果字段不是静态字段的话,要传入反射类的对象.如果传null是会报java.lang.NullPointerException

  2. 如果字段是静态字段的话,传入任何对象都是可以的,包括null

获取属性的值


public class Test  {
    public static String num1 = "abc";
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //使用反射第一步:获取操作类FieldDemo所对应的Class对象
        Class <?>cls = Class.forName("com.abc.test.Test");
        //使用FieldDemo类的class对象生成 实例
        Object obj = cls.newInstance();
        //通过Class类中getField(String name): 获取类特定的方法,name参数指定了属性的名称
        Field field = cls.getField("num1");

        //拿到了Field类的实例后就可以调用其中的方法了
        //方法:get(Object obj) 返回指定对象obj上此 Field 表示的字段的值
        System.out.println("属性值:  " + field.get(obj));

        //方法: set(Object obj, Object value)  将指定对象变量上此 Field 对象表示的字段设置为指定的新值
        field.set(obj, "新值");
        System.out.println("修改属性值后 --> get(Object obj):  " + field.get(obj));
    }
}

运行结果:

属性值:  abc
修改属性值后 --> get(Object obj):  新值

get()传值

class A {
    int fild = 3;
    static int staticFild = 4;
}
public class Test  {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        Field field = A.class.getDeclaredField("fild");
        int a= (Integer)field.get(new A()) ;
//        int c= (Integer)field.get(null) ; //不是静态字段不能传null
        System.out.println(a);

        Field staticfield = A.class.getDeclaredField("staticFild");
        int b = (Integer)staticfield.get("") ;
        int d = (Integer)staticfield.get(null) ;
        System.out.println(b);
        System.out.println(d);
    }
}

运行结果

3
4
4

set(Object obj, Object value)

向obj对象的这个Field设置新值value

将指定对象变量上此 Field 对象表示的字段设置为指定的新值.


public class Test  {
    public static String num1 = "abc";
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //使用反射第一步:获取操作类FieldDemo所对应的Class对象
        Class <?>cls = Class.forName("com.abc.test.Test");
        //使用FieldDemo类的class对象生成 实例
        Object obj = cls.newInstance();
        //通过Class类中getField(String name): 获取类特定的方法,name参数指定了属性的名称
        Field field = cls.getField("num1");

        //拿到了Field类的实例后就可以调用其中的方法了
        //方法:get(Object obj) 返回指定对象obj上此 Field 表示的字段的值
        System.out.println("属性值:  " + field.get(obj));

        //方法: set(Object obj, Object value)  将指定对象变量上此 Field 对象表示的字段设置为指定的新值
        field.set(obj, "新值");
        System.out.println("修改属性值后 --> get(Object obj):  " + field.get(obj));
    }
}

运行结果:

属性值:  abc
修改属性值后 --> get(Object obj):  新值

通过set(Object obj,value)重新设置新的属性值,并且当我们需要获取私有属性的属性值得时候,我们必须设置Accessible为true,然后才能获取

public static void main(String[] args) throws NoSuchFieldException,
SecurityException,
IllegalArgumentException,
IllegalAccessException {
    Person person = new Person();
    person.setName("VipMao");
    person.setAge(24);
    person.setSex("男");
    //通过Class.getDeclaredField(String name)获取类或接口的指定属性值。  
    Field f1 = person.getClass().getDeclaredField("name");
    System.out.println("-----Class.getDeclaredField(String name)用法-------");
    System.out.println(f1.get(person));
    System.out.println("-----Class.getDeclaredFields()用法-------");
    //通过Class.getDeclaredFields()获取类或接口的指定属性值。  
    Field[] f2 = person.getClass().getDeclaredFields();
    for (Field field: f2) {
        field.setAccessible(true);
        System.out.println(field.get(person));
    }
    //修改属性值  
    System.out.println("----修改name属性------");
    f1.set(person, "Maoge");
    //修改后再遍历各属性的值  
    Field[] f3 = person.getClass().getDeclaredFields();
    for (Field fields: f3) {
        fields.setAccessible(true);
        System.out.println(fields.get(person));
    }
}

运行结果:

-----Class.getDeclaredField(String name)用法-------  
VipMao  
-----遍历属性值-------  
VipMao  
24  
男  
----修改name属性后再遍历属性值------  
Maoge  
24  
男


























  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

?abc!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值