2021.5.24:Field类——访问字段
学习自:访问字段 - 廖雪峰的官方网站
Field类型——字段类型
对任意的一个Object实例,只要我们获取了它的Class,就可以获取它的一切信息。
Class类提供了以下几个方法来获取字段:
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类,且不必是public)
- Field getFields():获取所有public的field(包括父类)
- Field getDeclaredFields():获取当前类的所有field(不包括父类,且不必是public)
以上Field表示是Field类型。
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; }
上述代码首先获取Student的Class实例,然后,分别获取public字段、继承的public字段以及private字段,打印出的Field类似:
public int Student.score public java.lang.Person.name private int Student.grade
一个Field对象包含了一个字段的所有信息:
- getName():返回字段名称,如“name”;
- getType():返回字段类型,也是一个Class实例,例如:String.class;
- getModifiers():返回字段修饰符,这是一个int类型变量,不同bit代表不同的含义
以String的value字段为例,它的定义是:
public final class String{ private final byte[] value; }
我们用反射获取该字段的信息,代码如下:
Field f = String.class.getDeclaredField("value"); f.getName(); // "value" f.getType(); // class [B 表示byte[]类型 int m = f.getModifiers(); Modifier.isFinal(m); // true Modifier.isPublic(m); // false Modifier.isProtected(m); // false Modifier.isPrivate(m); // true Modifier.isStatic(m); // false
获取字段值
利用反射拿到字段的一个Field实例只是第一步,我们还可以拿到一个实例对应的该字段的值。
例如,对于一个Person实例,我们可以先拿到name字段对应的Field,再获取这个实例的name字段的值:
import java.lang.reflect.Field; 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"); Object value = f.get(p); System.out.println(value); } } class Person{ private String name; public Person(String name){ this.name=name; } }
上述代码①先获取Class实例c,②再获取Field实例f,然后,③用Field.get(Object)获取指定实例的指定字段的值。
运行代码,如果不出意外,会得到一个IllegalAccessException,这是因为name被定义为一个private字段。要修复错误,有两个方法:①将private修改为public;②在调用Object value = f.get(p);前,先写一句:
f.setAccessible(true);
调用Field.setAccessible(true)的意思是,别管这个字段是否为public,全都允许访问。
不过,我们访问字段时,通常是直接访问:p.name,反射是一种非常规的用法,它更多地是给工具或者底层框架来使用,目的是在不知道目标实例的任何信息的情况下,获取特定字段的值。
设置字段值:Field.set(Object,Object)
Field.set(Object,Object):设置字段值,第一个Object是指定的实例,第二个Object是待修改的值。
Person p = new Person("Xiao Ming"); Class c = person.getClass(); Field f = c.getDeclaredField("name"); f.setAccessible(true); f.set(p,"Xiao Hong");
修改非public字段,需要首先调用setAccessible(true);
总结
1、字段类型——Field
通过Class实例,可以获得一个class的所有字段信息,主要是四种方法:
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field getFields():获取所有public的field(包括父类)
- Field getDeclaredFields():获取当前类的所有field(不包括父类)
获取Field对象后,可以进一步获取字段信息:
- getName():返回字段名称,如“name”;
- getType():返回字段类型,也是一个Class实例,例如:String.class;
- getModifiers():返回字段修饰符,int类型,不同bit代表不同的含义
用法:
Field f = String.class.getDeclaredField("value"); f.getName(); // "value" f.getType(); // class [B 表示byte[]类型 int m = f.getModifiers();
2、获取字段值——Field.get(obj)
Object obj = new XXX(...); Class cls = obj.getClass(); Field f = c.getDeclaredField(name); Object value = f.get(obj);
如果要获取private字段值,还要在get前添加一句:
f.setAccessible(true);
3、设置字段值——Field.set( obj , value )
Object obj = new XXX(...); Class cls = obj.getClass(); Field f = cls.getDeclaredField( name ); f.set(obj , value);
同样,要修改非public字段值,也要写:
f.setAccessible(true);

浙公网安备 33010602011771号