JAVA-通过反射获取任意类的字段
一、获取Class实例
要通过反射来获取类的信息,首先要获取到Class实例,获取Class实例的方法有三种:
-
通过
class的静态变量class获取Class cls = User.class; -
通过实例变量的
getClass()方法获取User user = new User(); Class cls = user.getClass(); -
知道
getClass()的完整类名,可以通过静态方法Class.foName()获取Class cls = Class.forName("完整类名");
(一)通过Class实例创建对应类型的实例
-
如果获取到了一个
Class实例,通过该Class实例来创建对应类型的实例:// 获取String的Class实例: Class cls = User.class; // 创建一个String实例: User user = (User) cls.newInstance();
通过Class.newInstance()可以创建类的实例,局限是:只能调用public的无参数构造方法。带参数的构造方法或者非public的构造方法都无法通过Class.newInstance()调用。
二、字段和字段值
(一)获取字段
Class类提供了以下几个方法来获取Field:
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
在上一篇介绍反射概念文章的最后简单的使用Field:
Class cls = User.class;
System.out.println(cls.getName());
System.out.println(cls.getPackage());
System.out.println(cls.getSuperclass());
// 获取所有public的field(包括父类)
Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
// 获取当前类的field(不包括父类)
Field[] fields2 = cls.getFields();
for (int i = 0; i < fields2.length; i++) {
System.out.println(fields2[i]);
}
Field对象包含了一个字段的所有信息。
getName():返回字段名称;getType():返回字段类型,也是一个Class实例;getModifiers():返回字段的修饰符,是一个int,不同的位表示不同的含义。
比如获取User的name字段:
Field field = User.class.getDeclaredField("name");
System.out.println(field.getName());
System.out.println(field.getType());
(二)获取字段值
因为Field的get()方法只能接收Object作为参数,所以在得到参数t后要将其转为Object。
public void getFieldValue(T t) throws NoSuchFieldException, IllegalAccessException {
Object obj = (Object)t;
Class cls = obj.getClass();
Field field = cls.getDeclaredField("name");
//因为main类一般是无法访问private字段的,所以需要设置可访问权限为true
field.setAccessible(true);
Object name = field.get(obj);
System.out.println(name);
}
获取到字段值后,自然可以设置字段值。通过Field.set(Object, Object)方法可以设置字段值。
public void setFieldValue(T t) throws NoSuchFieldException, IllegalAccessException {
Object obj = (Object) t;
Class cls = obj.getClass();
Field field = cls.getDeclaredField("name");
field.setAccessible(true);
System.out.println(field.get(obj));
field.set(obj, "abcd");
System.out.println(field.get(obj));
}