我们知道在Java的反射机制中,最核心的一个类就是Class类。

Class类中提供了两个常用的获取类的成员变量的方法。

方法1 getFields()

/**
 * Returns an array containing {@code Field} objects reflecting all
 * the accessible public fields of the class or interface represented by
 * this {@code Class} object.
 *
 * <p> If this {@code Class} object represents a class or interface with no
 * no accessible public fields, then this method returns an array of length
 * 0.
 *
 * <p> If this {@code Class} object represents a class, then this method
 * returns the public fields of the class and of all its superclasses.
 *
 * <p> If this {@code Class} object represents an interface, then this
 * method returns the fields of the interface and of all its
 * superinterfaces.
 *
 * <p> If this {@code Class} object represents an array type, a primitive
 * type, or void, then this method returns an array of length 0.
 *
 * <p> The elements in the returned array are not sorted and are not in any
 * particular order.
 *
 * @return the array of {@code Field} objects representing the
 *         public fields
 * @throws SecurityException
 *         If a security manager, <i>s</i>, is present and
 *         the caller's class loader is not the same as or an
 *         ancestor of the class loader for the current class and
 *         invocation of {@link SecurityManager#checkPackageAccess
 *         s.checkPackageAccess()} denies access to the package
 *         of this class.
 *
 * @since JDK1.1
 * @jls 8.2 Class Members
 * @jls 8.3 Field Declarations
 */
@CallerSensitive
public Field[] getFields() throws SecurityException {
    checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
    return copyFields(privateGetPublicFields(null));
}

从注释上可以看出来,这个方法是用来获取一个类和其所有父类中被public修饰符修饰的成员变量的。

方法2 getDeclaredFields()

/**
 * Returns an array of {@code Field} objects reflecting all the fields
 * declared by the class or interface represented by this
 * {@code Class} object. This includes public, protected, default
 * (package) access, and private fields, but excludes inherited fields.
 *
 * <p> If this {@code Class} object represents a class or interface with no
 * declared fields, then this method returns an array of length 0.
 *
 * <p> If this {@code Class} object represents an array type, a primitive
 * type, or void, then this method returns an array of length 0.
 *
 * <p> The elements in the returned array are not sorted and are not in any
 * particular order.
 *
 * @return  the array of {@code Field} objects representing all the
 *          declared fields of this class
 * @throws  SecurityException
 *          If a security manager, <i>s</i>, is present and any of the
 *          following conditions is met:
 *
 *          <ul>
 *
 *          <li> the caller's class loader is not the same as the
 *          class loader of this class and invocation of
 *          {@link SecurityManager#checkPermission
 *          s.checkPermission} method with
 *          {@code RuntimePermission("accessDeclaredMembers")}
 *          denies access to the declared fields within this class
 *
 *          <li> the caller's class loader is not the same as or an
 *          ancestor of the class loader for the current class and
 *          invocation of {@link SecurityManager#checkPackageAccess
 *          s.checkPackageAccess()} denies access to the package
 *          of this class
 *
 *          </ul>
 *
 * @since JDK1.1
 * @jls 8.2 Class Members
 * @jls 8.3 Field Declarations
 */
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
    checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
    return copyFields(privateGetDeclaredFields(false));
}

从注释上可以看出来,这个方法是用来获取一个类中的所有成员变量的,即包括被public、protected、defautl和private修饰符修饰的所有成员变量。

但是这个方法,其基类的一个成员变量都不会拿得到。

取本类和基类的所有成员变量

要取本类和基类的所有成员变量,Class类中提供的两种获取类中成员变量的方法都不能直接实现这个需求,但是可以通过简单的while循环来实现。

// 取所有字段(包括基类的字段)
Field[] allFields = clazz.getDeclaredFields();
Class superClass = clazz.getSuperclass();
while (superClass != null) {
  Field[] superFileds = superClass.getDeclaredFields();
  allFields = ArrayUtils.addAll(allFields, superFileds);
  superClass = superClass.getSuperclass();
}

这样就取到了类中的所有成员变量,包括基类的成员变量。

"父爱无声,但它一直都在。"

02-10 12:29