最近在写注解相关代码的时候经常会使用到反射机制,关于Class
类的两个方法getFields
和getDeclaredFields
有一些疑惑,这两个方法到底哪里不一样,有什么区别呢。最好的教程就是源码,直接进入源码可以看到如下注释:
/**
* 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));
}
/**
* 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));
}
以上注释的意思大概就是说:
-
getFields
方法只会返回public
修饰符修饰的属性,且能返回父类属性 -
getDeclaredFields
方法会返回当前类的所有声明属性,包括public
、private
、protected
、default
、static
修饰符修饰的属性,但是不能返回父类的属性。
下面,以一个例子说明,更加简洁易懂:
/**
* 父类
*/
public class OldStrudent {
private String oldName;
public boolean oldSex;
}
/**
* 子类
*/
public class Student extends OldStrudent {
private String name;
private Integer score;
private boolean sex;
public String teacher;
private static String id;
}
/**
* 测试类
*/
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) {
Field[] fields = Student.class.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("---------");
Field[] decFields = Student.class.getDeclaredFields();
for (Field field : decFields) {
System.out.println(field.getName());
}
}
}
/**
* 输出结果:
* teacher
* oldSex
* ---------
* name
* score
* sex
* teacher
* id
*/
同理,Class
的getMethod
和getDeclaredMethods
方法也是这个逻辑。