首页 > 解决方案 > 获取Java中类的字段名称

问题描述

我正在尝试以自动方式为 Java 中的类的字段生成 CSV 映射,因为我需要多次使用它。

我有以下方法来尝试获取字段名称:(其中 CSV 标头类似于“DB_NAME|FIELD_NAME|ADDITIONAL_F1|ADDITIONAL_F2”)

package util;

import java.lang.reflect.Field;

public class CsvAttributesMappingGenerator {
public static String generateCsvAttributesMapping(Class<?> model) {

    StringBuilder csvBuilder = new StringBuilder();

    Field[] fieldList = model.getDeclaredFields();
    for (Field field : fieldList) {
        //field.setAccessible(true);
        csvBuilder.append(field.getName().replaceAll("(.)(\\p{Upper})", "$1_$2").toUpperCase());
        csvBuilder.append("|");
        csvBuilder.append(field.getName());
        csvBuilder.append("||\n");
    }
    return formatOutput(csvBuilder.toString());
}

private static String formatOutput(String classText) {
    String delimiter = "\n******************************\n";
    return String.format("%s%s%s", delimiter, classText, delimiter);
}

}

和一个测试电话,如:

import objects.User;
import org.junit.Test;
import util.CsvAttributesMappingGenerator;

public class CsvAttributesMappingGeneratorTest {

@Test
public void testGenerationWithObject() {
    System.out.println(CsvAttributesMappingGenerator.generateCsvAttributesMapping(User.class));
}
}

被解析的对象结构如下:包对象;

public class User {
private String userName;
private String userEmail;
private int userAge;
private String otherDetails;
// getters, setters and all args constuctor here
}

输出应该有多个行,例如 FIELD_NAME|fieldName|| 骆驼装的物品应该从给定的班级中收集。正如我在几个示例中看到的那样,我尝试使用 Java 反射 API,但我得到了一个奇怪的字符串输出。(不是序列化的@randomCharsLikeName)。尝试了 toString() 和其他肮脏的技巧,但没有任何效果。

有人可以给我一点提示吗?或者至少告诉我是否可以做我尝试过的事情?提前致谢!

编辑:问题中呈现的当前代码原型在隔离环境(单独的新项目)中工作并显示预期输出。尽管集成在我试图将其集成到的整个应用程序中,但它不起作用。我将继续研究并让您知道根本原因(在我使用的真实应用程序中,我也在使用 lombok 进行课程(

@AllArgsConstructor、@NoArgsConstructor、@Data、@ToString

),但老实说,我不认为这可能是使用反射时的问题)

标签: javareflection

解决方案


同时我发现了这个问题。当我对生成器进行原型制作时,我使用了:

csvBuilder.append(field.getClass().getName().replaceAll("(.)(\\p{Upper})", "$1_$2").toUpperCase());

它产生了类似的输出JAVA.LANG.REFLECT._FIELD|java.lang.reflect.Field||

因为我只是忘记了我实际上改进了它以使用实际的类对象作为函数的参数。在提出问题之前,我对代码进行了一些 Sonar 修复,但没有注意到我修复了 WARN 以删除.getClass()方法调用,因为我已经传入了一个类(我认为这不会有什么不同,因为它只是一个警告)。今日道德提示 - 永远不要忽视警告。

因此,问题中提供的代码片段现在可以在一个孤立的虚拟项目中正常工作,并且还可以使用固定行集成到一个更复杂的项目中:

csvBuilder.append(field.getName().replaceAll("(.)(\\p{Upper})", "$1_$2").toUpperCase());

同样正如评论中有人建议的那样,field.setAccessible(true);可以将其删除,因为它对于该方法的目的是无用的。


推荐阅读