【反射】Java反射的使用-获得字段属性

738 阅读2分钟

反射的使用

获得类的字段属性

下面是大Class提供的方法:

  • getField()只能获取public字段
  • getDeclaredField()可以获取所有字段,不考虑修饰符
  • getFields()获取所有public字段
  • getDeclaredFields()获取所有字段
public class Main {
    public static void main(String[] args) throws Exception {
        Class stdClass = Student.class;
        // 获取public字段"score":
        System.out.println(stdClass.getField("score"));
        // 获取继承的public字段"name":
        System.out.println(stdClass.getField("name"));
        // 获取private字段"grade":
        System.out.println(stdClass.getDeclaredField("grade"));
    }
}

class Student extends Person {
    public int score;
    private int grade;
}

class Person {
    public String name;
}

分析

输出:
public int Student.score
public java.lang.String Person.name
private int Student.grade

通过getField()方法可以获得类的属性,传入参数(需要被查找的属性名),获得的是一个Field对象。

然后该Field对象里又有很多方法。

一个Field对象包含了一个字段的所有信息:

  • getName():返回字段名称,例如,"name"
  • getType():返回字段类型,也是一个Class实例,例如,String.class
  • getModifiers():返回字段的修饰符,它是一个int,不同的bit表示不同的含义。
  • getGenericType: 返回泛型的类型,比如: String.class
  • getAnnotation(): 返回注解对象,参数为要获得的注解的反射对象(Class),比如传入Data.class

当使用getModifiers():返回字段的修饰符的值,当想要进一步判断时,需要使用Modifier类。

可以使用Modifier类中的相应方法来判断:

  • Modifier.isPublic(int)
  • Modifier.isPrivate(int)
  • Modifier.isProtected(int)
  • Modifier.isStatic(int)
  • Modifier.isFinal(int)
Field score = stdClass.getField("score");
int modifiers = score.getModifiers();
System.out.println(Modifier.isFinal(modifiers));

·····


上面是获得类的属性信息,下面介绍获得实例的属性值。

获得实例的字段值

Field类还有一个方法get(),参数:要获得属性值的对象。

public class Main {

    public static void main(String[] args) throws Exception {
        Object p = new Person("Xiao Ming");
        Class c = p.getClass();
        Field f = c.getDeclaredField("name");
        f.setAccessible(true);
        Object value = f.get(p);
        System.out.println(value); // "Xiao Ming"
    }
}

class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
}

分析

大家可能看到我新加了一行f.setAccessible(true);

去试试去掉会怎么样,大家应该会出现class thread.Main cannot access a member of class thread.Person with modifiers "private", 这种情况表明我们没有权限去访问该字段的值。

  • 默认情况下,由于私有字段有私有访问权限修饰,所以即使通过反射获得 Field 对象,只能获得它的一些字段信息。但是无法读取其值,
  • 当调用 setAccessible(true) 后,此 Field 对象会取消 Java 访问修饰符的检查
  • 这就允许你调用 f.get() 方法来获取私有字段的值
  • 修改非public字段,需要首先调用setAccessible(true)

同理,获得属性值使用Fieldget()方法,当为其设置值时可以使用set()方法,

参数为: 需要被设置属性的对象 传入的值。

比如: f.set(p, "guagua");