【问题标题】:How to get fields names of a class inside another class?如何在另一个类中获取一个类的字段名称?
【发布时间】:2021-11-09 18:10:59
【问题描述】:

我们正在从 DTO 类创建 CSV 文件,使用反射来获取所有列名的名称。 ClassName.class.getDeclaredFields() 为我们提供了所有列名的数组。

我们有一个用例,我们有具有组合关系的类,如下所示:

public class Book {
  private String title;

  private Author author;
}

public class Author {
  private String name;

  private Integer age:
}

这里的 Book 是根类,即最终的 CSV 将被命名为 books.csv

使用Book.class.getDeclaredFields(),我们只获取字段名称title 和author,但我们还想要来自Author 类的字段名称(姓名和年龄),有没有办法得到这些?

【问题讨论】:

  • Author.class.getDeclaredFields() 不起作用吗?或者您是否正在寻找一个不涉及知道authorBook 中的类型的解决方案?
  • 永远不要使用 'int' 或 'Integer' 年龄。只存储生日。与年龄不同,它不会每年都在变化,您可以根据它完美地找到年龄。 name 和 age 不是 Book 的一部分,那么它为什么会返回它呢?既然作者的类型不固定,那么这个过程怎么能分辨出来呢?
  • @bob 您可以使用field.getType().isPrimitive() 检查Field 是否为原始类型。如果它不是原始的,您再次调用field.getType().getDeclaredFields()。这可能必须为每个子类型递归地完成。
  • @bob isPrimitive() 将为字符串返回 false。所以你可能必须这样做:var type = field.getType(); if(type.isPrimitive() || type.isAssignableFrom(String.class)) {...} 还要检查它是否是一个字符串。还要涵盖包装类,请参阅this post
  • @AmalK type.isAssignableFrom(String.class) 将是 true 如果 typeObject。也许,你只是想要type == String.class

标签: java reflection


【解决方案1】:

注意事项:

  • 远非最佳。
  • 不考虑循环引用问题。

根据您的模型,它会返回一个包含以下元素的列表:

  • 标题
  • 作者姓名
  • 作者年龄

用法:

ClassMetadataService cms = new ClassMetadataService();
List<String> properties = cms.getProperties(Book.class);

类定义:

package io.metadata;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ClassMetadataService {

    public List<String> getProperties(Class clazz) {
        List<String> properties = new ArrayList<>();
        this.collectProperties(new ArrayList<>(), clazz, properties);

        return properties;
    }

    private void collectProperties(List<String> pathNodes, Class clazz, List<String> properties) {
        for (Field field : clazz.getDeclaredFields()) {
            List<String> localPathNodes = new ArrayList<>(pathNodes);
            localPathNodes.add(field.getName());

            if (clazz.isPrimitive() || isJavaClass(field.getType())) {
                properties.add(localPathNodes.stream().collect(Collectors.joining(".")));
            } else {
                collectProperties(localPathNodes, field.getType(), properties);
            }
        }
    }

    private Boolean isJavaClass(Class clazz) {
        List<Class> javaClass = Arrays.asList(
                // ....
                Boolean.class,
                Byte.class,
                Short.class,
                Integer.class,
                Long.class,
                Float.class,
                Double.class,
                BigDecimal.class,
                BigInteger.class,
                Character.class,
                String.class,
                LocalDate.class,
                LocalDateTime.class
                // ....
        );

        return javaClass.stream().anyMatch(jc -> jc.equals(clazz));
    }
}


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多