Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从类中获取所有字段(即使是私有字段和继承字段)_Java_Reflection - Fatal编程技术网

Java 从类中获取所有字段(即使是私有字段和继承字段)

Java 从类中获取所有字段(即使是私有字段和继承字段),java,reflection,Java,Reflection,我正在做大学项目。 我需要从类中获取所有字段。甚至是私人的和继承的。我尝试获取所有声明的字段,然后转换到超级类并重复。 我的代码片段: private void listAllFields(Object obj) { List<Field> fieldList = new ArrayList<Field>(); while (obj != null) { fieldList.addAll(Arrays.asList(obj.getClass

我正在做大学项目。
我需要从类中获取所有字段。甚至是私人的和继承的。我尝试获取所有声明的字段,然后转换到超级类并重复。 我的代码片段:

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
试试这些

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 ) );
        }
    }
}

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

是的,可以使用反射

在您的代码集
字段中。setAccessible(true)

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

在提取值之前,必须使用setAccessible to true。有时JVM不允许提取私有变量,它可能会给出安全异常

obj = obj.getClass().getSuperclass().cast(obj);
这一行并没有达到您期望的效果。强制转换一个
对象
实际上并不会改变它,它只是告诉编译器将其视为其他对象

例如,您可以将
列表
强制转换为
集合
,但它仍然是
列表

但是,通过超类循环访问字段可以在不强制转换的情况下正常工作:

Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
    // do something with current's fields
    current = current.getSuperclass();
}
Class current=yourClass;
而(current.getSuperclass()!=null){//我们不想处理Object.class
//对current的字段执行某些操作
current=current.getSuperclass();
}
顺便说一句,如果您有权访问Spring框架,那么有一种方便的方法可以循环一个类和所有超类的字段:

(另请参见我前面的回答:)

getDeclaredFields()
提供该类上的所有字段,包括
私有字段

getFields()
提供该类及其超类上的所有
public
字段

allFieldsFor(SomeClass.class).map(Field::getName).forEach(System.out::println);
如果
private
/
要保护超类的
方法,则必须重复调用
getSuperclass()
,然后对超类对象调用
getDeclaredFields()

在前面询问的问题中,这里没有什么没有解释清楚的


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

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

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;
    }
private List getFields(T){
列表字段=新的ArrayList();
Class clazz=t.getClass();
while(clazz!=Object.class){
addAll(Arrays.asList(clazz.getDeclaredFields());
clazz=clazz.getSuperclass();
}
返回字段;
}

此解决方案使用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()) );
}
专用流所有字段(c类){
返回walkInheritanceTreeFor(c).flatMap(k->Arrays.stream(k.getDeclaredFields());
}
私有流walkInheritanceTreeFor(c类){
返回iterate(c,k->Optional.ofNullable(k.getSuperclass());
}
以下方法是从Streams.iterate建模的,但是Streams.iterate旨在创建无限流。此版本已修改为在从fetchNextFunction返回可选的.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
    );
}
私有流迭代(T种子,函数fetchNextFunction){
requirennull(fetchNextFunction);
迭代器迭代器=新迭代器(){
private Optional t=可选的。不可用的(种子);
公共布尔hasNext(){
返回t.isPresent();
}
公共交通工具{
T v=T.get();
t=fetchNextFunction.apply(v);
返回v;
}
};
returnstreamsupport.stream(
Spliterators.spliteratorUnknownSize(迭代器,Spliterator.ORDERED | Spliterator.IMMUTABLE),
假的
);
}

这里有一个解决方案

//我的目标

    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);
    }
//如果要从多个超类获取字段,则可以使用以下代码进行迭代:

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

我不知道字段的名称-这必须是通用的解决方案。我知道我可以使字段可访问,但首先我必须知道父私有字段的名称。我的问题是获取该名称,而不是在我拥有该名称时访问它。对于私有字段,你需要知道名称,对于继承的使用getSuperclass()方法,你只需要像这样运行所有declaredfields,我需要这个概念将任何对象序列化到我的内部数据库:)此应用程序是“编程数据库引擎”项目当然要获得所有继承的字段,必须使用递归,如@DmitryKuskov所述,您不能在注释中使用该符号。您必须使用
[label](url)
。如果一个类具有多个继承级别,则可能的重复项不起作用。如果该超类继承另一个类,您仍然可以通过迭代超类来获取该超类继承的类字段。下面是代码:Class clazz=Student.Class;虽然(clazz!=null){System.out.println(clazz.getName());clazz=clazz.getSuperclass();}我知道,但复制示例代码的人可能不会。由于原始问题是针对所有继承字段提出的,因此您的解决方案目前无法回答该问题。也许你可以编辑一点代码来反映这一点。这对我不起作用,我想从超类中获取字段值,在这里我得到类对象。
    Class clazz = Student.class;
    while (clazz != null) {
      clazz= clazz.getSuperclass(); 
    }