【问题标题】:Java reflection get all private fieldsJava反射获取所有私有字段
【发布时间】:2013-02-25 06:13:05
【问题描述】:

我想知道有没有办法在 java 中获取某个类的所有私有字段及其类型。

例如,假设我有一个班级

class SomeClass {
    private String aaa;
    private SomeOtherClass bbb;
    private double ccc;
}

现在我想获取 SomeClass 类的所有私有字段(aaabbbccc)(不知道所有字段的名称)并检查它们的类型。

【问题讨论】:

  • @atk 没有人强迫你回答;但是对于我们中的许多人来说,从谷歌上登陆这个问题,最佳答案是一个比阅读关于反思的长篇文章更简洁的解释。甚至像这样的长尾问题也促成了今天的 SO。

标签: java reflection field private


【解决方案1】:

可以通过Class的方法getDeclaredFields()获取所有字段。然后您必须检查每个字段的修饰符以找到私有字段:

List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
    if (Modifier.isPrivate(field.getModifiers())) {
        privateFields.add(field);
    }
}

请注意,getDeclaredFields() 不会返回继承的字段。

最终,您可以通过 Field.getType() 方法获得字段的类型。

【讨论】:

  • 我认为我正在处理编译类这一事实使其非常不方便,因为返回的字段具有m0m1 等名称,并且是@987654328 类型@。这可能是因为我试图在转换为接口的 Spring Bean 上使用反射?
【解决方案2】:

您可以使用Modifier 来确定字段是否为私有。请务必使用getDeclaredFields 方法确保从类中检索私有字段,调用getFields 只会返回公共字段。

public class SomeClass {

    private String aaa;
    private Date date;
    private double ccc;
    public int notPrivate;

    public static void main(String[] args) {
        List<Field> fields = getPrivateFields(SomeClass.class);
        for(Field field: fields){
            System.out.println(field.getName());
        }
    }

    public static List<Field> getPrivateFields(Class<?> theClass){
        List<Field> privateFields = new ArrayList<Field>();

        Field[] fields = theClass.getDeclaredFields();

        for(Field field:fields){
            if(Modifier.isPrivate(field.getModifiers())){
                privateFields.add(field);
            }
        }
        return privateFields;
    }
}

【讨论】:

  • @AfzaalAhmadZeeshan 为什么将我的编辑“clazz”更改为“class”,而我们显然需要使用变量“clazz”而不是关键字“class”
  • 我很抱歉这个错误,我认为这是一个错误,因为没有任何变量与文档或代码相关联!请原谅我……
  • @AfzaalAhmadZeeshan 有一个变量,它在方法的参数中。不过,您是否愿意撤销您的更改,因为我无法更改它。
【解决方案3】:

尝试来自 apache commons-lang3 的 FieldUtils

FieldUtils.getAllFieldsList(Class<?> cls)

【讨论】:

    【解决方案4】:

    使用 Java 8:

    Field[] fields = String.class.getDeclaredFields();
    List<Field> privateFieldList = Arrays.asList(fields).stream().filter(field -> Modifier.isPrivate(field.getModifiers())).collect(
            Collectors.toList());
    

    【讨论】:

      【解决方案5】:

      检查字段是否为私有

      您可以使用Modifier.isPrivate过滤字段

      import java.lang.reflect.Field;
      import java.lang.reflect.Modifier;
      // ...
      Field field = null;
      // retrieve the field in some way
      // ...
      Modifier.isPrivate(field.getModifiers())
      

      在单个 Field 对象上,如果字段为 private,则返回 true


      收集一个类的所有字段

      收集所有字段,请使用:

      1) 如果您只需要类的字段而不需要从类层次结构中获取的字段,您可以简单地使用:

      Field[] fields = SomeClass.class.getDeclaredFields();
      

      2) 如果您不想重新发明轮子并获得类层次结构的所有字段,您可以依赖 Apache Commons Lang 版本 3.2+,它提供了 FieldUtils.getAllFieldsList

      import java.lang.reflect.Field;
      import java.util.AbstractCollection;
      import java.util.AbstractList;
      import java.util.AbstractSequentialList;
      import java.util.Arrays;
      import java.util.LinkedList;
      import java.util.List;
      
      import org.apache.commons.lang3.reflect.FieldUtils;
      import org.junit.Assert;
      import org.junit.Test;
      
      public class FieldUtilsTest {
      
          @Test
          public void testGetAllFieldsList() {
      
              // Get all fields in this class and all of its parents
              final List<Field> allFields = FieldUtils.getAllFieldsList(LinkedList.class);
      
              // Get the fields form each individual class in the type's hierarchy
              final List<Field> allFieldsClass = Arrays.asList(LinkedList.class.getFields());
              final List<Field> allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields());
              final List<Field> allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields());
              final List<Field> allFieldsParentsParentsParent = Arrays.asList(AbstractCollection.class.getFields());
      
              // Test that `getAllFieldsList` did truly get all of the fields of the the class and all its parents 
              Assert.assertTrue(allFields.containsAll(allFieldsClass));
              Assert.assertTrue(allFields.containsAll(allFieldsParent));
              Assert.assertTrue(allFields.containsAll(allFieldsParentsParent));
              Assert.assertTrue(allFields.containsAll(allFieldsParentsParentsParent));
          }
      }
      

      【讨论】:

        【解决方案6】:

        你的意思是喜欢

        Field[] fields = SomeClass.class.getDeclaredFields();
        

        【讨论】:

        • 这不包括任何继承的字段。
        猜你喜欢
        • 2020-08-04
        • 1970-01-01
        • 1970-01-01
        • 2021-12-07
        • 2011-10-06
        • 1970-01-01
        • 1970-01-01
        • 2015-07-08
        • 2022-01-08
        相关资源
        最近更新 更多