java反射以字符串形式获取特定的声明字段值

java反射以字符串形式获取特定的声明字段值,java,reflection,java-8,Java,Reflection,Java 8,我在RequestDto中有一个声明字段as(RequestDto有许多声明字段,但我只需要这个自定义字段) 我想将这个声明的字段名定制为字符串 像字符串名-“自定义”(但自定义必须是动态的) 解决方案必须不修改默认的getter和setter 实际上,我有一个问题,比如当处理requestDto进行内容验证时,如果requestDto中的一个字段有一个坏数据,我应该提供一条错误消息以及字段名作为字符串,该字符串包含一个不相关的数据 问题是,将来在RequestDto中修改自定义字段时,修改它的

我在RequestDto中有一个声明字段as(RequestDto有许多声明字段,但我只需要这个自定义字段)

我想将这个声明的字段名定制为字符串

字符串名-“自定义”(但自定义必须是动态的)

解决方案必须不修改默认的getter和setter


实际上,我有一个问题,比如当处理requestDto进行内容验证时,如果requestDto中的一个字段有一个坏数据,我应该提供一条错误消息以及字段名作为字符串,该字符串包含一个不相关的数据

问题是,将来在RequestDto中修改自定义字段时,修改它的人甚至不知道自定义字段被设置为string并被使用,因此我只想将自定义字段名作为RequestDto中的string,因此每当更改字段值时,我都会在string中得到更改的名称

 private static String getCustom(RequestDto requestDto) throws NoSuchFieldException, IllegalAccessException {
    Field field = requestDto.getClass().getDeclaredField("custom");
    field.setAccessible(true);
    return (String) field.get(requestDto);
}
如果它对您来说不够“动态”:


编辑:在你在评论中添加了最重要的信息“如果将来有人更改了这个名字会怎么样”。。。好。。。那么,反思不是出路

然后,我宁愿使用
函数或类似的函数,例如:

static String getCustom(RequestDto requestDto, Function<RequestDto, String> customExtractor) {
  return customExtractor.apply(requestDto);
}
如果该字段在将来被重构,那么该部分也将被自动重构(嗯……可能取决于您的IDE;-)。但是它不会将适当的字段名作为错误消息提供给您。请注意,如果获取正确字段的唯一属性是它的名称,那么没有一种很好的方法来获取它。如果要在字段中添加注释,则可以过滤并获取带有该特定注释的字段。这样你就不需要知道实际的名字。。。但反问题是:如何确保只有1个字段使用该注释进行了注释?我宁愿重新设计应用程序的特定部分。我不会向“客户”透露任何字段。如果这意味着我在错误消息和字段名中可能有不同的名称,那么就这样吧

还要注意,现代IDE也允许重构字符串(当您重命名字段时)。您只需要确保这些信息在团队中传播(以及未来的成员)


使用反射的上一个答案:

如果使用dynamic,您的意思是,它必须以该名称开头或包含该名称,则您可能希望使用以下内容,即,对它们进行迭代以筛选出感兴趣的字段:

private static String getCustom(RequestDto requestDto) throws NoSuchFieldException, IllegalAccessException {
    return Arrays.stream(requestDto.getClass().getDeclaredFields())
            .filter(e -> e.getName().startsWith("custom"))
            .findFirst() // if the first match suffices
            .map(f -> {  // you may want to extract that part if you use streams
                f.setAccessible(true);
                try {
                    return (String) f.get(requestDto);
                } catch (IllegalAccessException e) {
                    // TODO whatever you need to do...
                    return null;
                }
            }).orElseThrow(IllegalArgumentException::new); // or whatever suites better
}
如果您需要按类型或注释等进行过滤,此示例应该足够了。只需相应地调整过滤器即可


如果它只是您需要的字段名称,那么它就是您想要的。

requestDto.getClass().getDeclaredField(“自定义”)//这个自定义值我想要动态你说的“动态”是什么意思?它是动态的。不管怎样,我编辑了我的答案。你说的“动态”是什么意思?在运行时,您必须在变量“get specific declared field”(获取特定声明字段)、“我只需要此自定义字段”)中包含名称—您希望如何指定要访问的字段?正如您所说,一个类中可能有许多字段。是什么使此字段与其他字段不同,以便您能够找到感兴趣的特定字段通常,注释用于此目的。一个字段是经过特殊注释的,在运行时,通过反射,所有字段都会搜索其中包含特定注释的字段。换句话说,您可以通过反射访问所有字段。
字段
类提供了有关该字段的所有信息。如果要查找名称未知的字段,必须使用其中一些信息。它可以是类型、名称(模式)、注释,实际的声明类或类似的东西。实际上,我有一个问题,比如当处理requestDto进行内容验证时,如果requestDto中的一个字段有错误数据,我应该提供一条错误消息以及字段名作为字符串,其中有一个不相关的数据。您的问题描述缺少关键部分关于您如何得出某个领域是“感兴趣”的结论的信息。你问题的答案完全取决于“细节”。
static String getCustom(RequestDto requestDto, Function<RequestDto, String> customExtractor) {
  return customExtractor.apply(requestDto);
}
RequestDto someRequest = ...;
getCustom(someRequest, RequestDto::getCustom);
private static String getCustom(RequestDto requestDto) throws NoSuchFieldException, IllegalAccessException {
    return Arrays.stream(requestDto.getClass().getDeclaredFields())
            .filter(e -> e.getName().startsWith("custom"))
            .findFirst() // if the first match suffices
            .map(f -> {  // you may want to extract that part if you use streams
                f.setAccessible(true);
                try {
                    return (String) f.get(requestDto);
                } catch (IllegalAccessException e) {
                    // TODO whatever you need to do...
                    return null;
                }
            }).orElseThrow(IllegalArgumentException::new); // or whatever suites better
}