从类中获取所有字段(甚至私有和继承)

时间:2013-04-30 08:58:31

标签: java reflection

我正在做大学项目 我需要从课堂上获得所有领域。甚至私人和继承。我试图获取所有声明的字段,然后转换为超类并重复。 我的代码片段:

private void listAllFields(Object obj) {
    List<Field> fieldList = new ArrayList<Field>();
    while (obj != null) {
        fieldList.addAll(Arrays.asList(obj.getClass().getDeclaredFields()));
        obj = obj.getClass().getSuperclass().cast(obj);
    }
    // rest of code

但它不起作用。在施法后tmpObj仍然是同一个类(不是超类) 我将不胜感激任何帮助如何解决铸造问题,或如何以不同的方式检索这些字段。

问题不是获取对字段的访问权限,而是获取字段的名称!
我这样管理:

private void listAllFields(Object obj) {
    List<Field> fieldList = new ArrayList<Field>();
    Class tmpClass = obj.getClass();
    while (tmpClass != null) {
        fieldList.addAll(Arrays.asList(tmpClass .getDeclaredFields()));
        tmpClass = tmpClass .getSuperclass();
    }
    // rest of code

10 个答案:

答案 0 :(得分:76)

obj = obj.getClass().getSuperclass().cast(obj);

此行不符合您的预期。转换Object实际上并没有改变它,它只是告诉编译器将其视为其他东西。

E.g。您可以将List投射到Collection,但它仍然是List

但是,通过超类循环访问字段可以正常工作而不需要转换:

Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
    // do something with current's fields
    current = current.getSuperclass();
}

顺便说一句,如果您可以访问Spring Framework,那么有一种方便的方法可以循环遍历类和所有超类的字段:
ReflectionUtils.doWithFields(baseClass, FieldCallback)
(另见我之前的答案:Access to private inherited fields via reflection in Java

答案 1 :(得分:31)

getDeclaredFields()为您提供该课程的所有字段,包括private个字段。

getFields()为您提供该类及其超类的所有public个字段。

如果您需要超级课程的private / protected种方法,则必须重复拨打getSuperclass(),然后拨打getDeclaredFields()超类对象。

javadocs

中没有明确解释这里的任何内容

答案 2 :(得分:8)

这是我用来获取对象的所有字段的方法

private <T> List<Field> getFields(T t) {
        List<Field> fields = new ArrayList<>();
        Class clazz = t.getClass();
        while (clazz != Object.class) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fields;
    }

答案 3 :(得分:3)

试试这些

How do I read a private field in Java?

Is it possible in Java to access private fields via reflection

Field.setAccessible(true)是您必须做的才能通过反射

进行访问
import java.lang.reflect.Field;

class B 
{
    private int i = 5;
}

public class A extends B 
{
    public static void main(String[] args) throws Exception 
    {
        A a = new A();
        Field[] fs = a.getClass().getSuperclass().getDeclaredFields();
        for (Field field : fs)
        {
            field.setAccessible(true);
            System.out.println( field.get( a ) );
        }
    }
}

答案 4 :(得分:1)

要获取超类字段,请使用getSuperclass()。从那里你可以获得超类的领域。

答案 5 :(得分:1)

是的,可以使用Reflection。

在您的代码集Field.setAccessible(true);

继续学习这个概念,但不要这样做: - )

答案 6 :(得分:1)

ClassName obj  =  new ClassName();
Field field  =   ClassName.class.getDeclaredField  ("name of the field");
field.setAccessible   (true);
DataType value  =  (DataType) field.get  (obj);

在提取值之前,必须使用setAccessible为true。有时JVM不允许提取私有变量,它可能会给出Security Exception。

答案 7 :(得分:1)

以前问过。

Access to private inherited fields via reflection in Java

在您的代码中,设置field.setAccessible(true);

答案 8 :(得分:1)

此解决方案使用Java 8流,对于那些在Java中学习函数式编程的人非常有用。它按照其他答案迭代getSuperclass和getDeclaredFields,但它以功能方式完成。

以下行将打印在SomeClass或其任何超类上找到的每个字段名称的名称。

allFieldsFor(SomeClass.class).map(Field::getName).forEach(System.out::println);

以下是逐步执行超类以创建字段流的代码。

private Stream<Field> allFieldsFor( Class c ) {
    return walkInheritanceTreeFor(c).flatMap( k -> Arrays.stream(k.getDeclaredFields()) );
}

private Stream<Class> walkInheritanceTreeFor( Class c ) {
    return iterate( c, k -> Optional.ofNullable(k.getSuperclass()) );
}

以下方法是从Streams.iterate建模的,但Streams.iterate旨在创建无限流。当从fetchNextFunction返回Optional.none()时,此版本已被修改为结束。

private <T> Stream<T> iterate( T seed, Function<T,Optional<T>> fetchNextFunction ) {
    Objects.requireNonNull(fetchNextFunction);

    Iterator<T> iterator = new Iterator<T>() {
        private Optional<T> t = Optional.ofNullable(seed);

        public boolean hasNext() {
            return t.isPresent();
        }

        public T next() {
            T v = t.get();

            t = fetchNextFunction.apply(v);

            return v;
        }
    };

    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize( iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE),
        false
    );
}

答案 9 :(得分:0)

这里是解决方案

//我的对象

    Student student =new Student();

    Field[] field2=student.getClass().getSuperclass().getDeclaredFields();
    Field[] field1=student.getClass().getDeclaredFields();
    
    Field [] all_Fields=new Field[field1.length+field2.length];
    
    
    //Joining field 1 and two
      System.arraycopy(field2, 0, all_Fields, 0, field2.length);
      System.arraycopy(field1, 0, all_Fields, field2.length, field1.length);
    

      //Printing all fields
    for(Field i:all_Fields)
    {
        System.out.println(i);
    }

///如果要从多个SuperClass中获取字段,则可以使用以下代码进行迭代:

    Class clazz = Student.class;
    while (clazz != null) {
      clazz= clazz.getSuperclass(); 
    }