Java反射获取特定的声明字段值作为字符串

时间:2018-11-29 11:08:07

标签: java reflection java-8

我在RequestDto中有一个声明字段(requestDto有很多声明的字段,但是我只想要这个自定义字段)

private String custom; 

我想获得这个声明的字段名称Custom作为String

String name-"custom"(but custom has to be dynamic)

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

实际上,我有一个问题,例如如果请求Dto中的字段之一包含错误数据,则应处理requestDto以进行内容验证,我应该提供错误消息以及字段名称作为字符串,其中包含不相关的数据< / p>

问题是,将来在RequestDto中修改自定义字段时,修改该字段的人甚至都不知道自定义字段已设置为字符串并被使用,因此我想将自定义字段名称作为RequestDto中的字符串只有,所以当字段值更改时,我会在字符串中获取更改的名称

2 个答案:

答案 0 :(得分:4)

编辑:在注释“如果将来有人更改此名称该怎么办”中添加了最重要的信息之后...好吧,那么思考就不可行了!

然后,我宁愿使用类似Function<RequestDto, String>之类的字词,例如:

static String getCustom(RequestDto requestDto, Function<RequestDto, String> customExtractor) {
  return customExtractor.apply(requestDto);
}

并通过以下方式调用它:

RequestDto someRequest = ...;
getCustom(someRequest, RequestDto::getCustom);

如果将来会重构该字段,那么该部分也会被重构,然后也会自动重构(嗯……可能取决于您的IDE ;-)。但是...它不会给您适当的字段名称作为错误消息。请注意,如果要获取正确的字段,唯一的属性就是它的名称,这不是一种捕获正确字段的好方法。如果要在字段上添加注释,则可以过滤并抓取具有该特定注释的字段。这样,您无需知道实际名称...而是反问:您如何确定只有1个字段使用该注释进行注释?我宁愿重新设计应用程序的特定部分。我不会向“客户端”公开任何字段。如果那意味着我在错误消息和字段名称中可能使用不同的名称,那就这样吧。

还请注意,现代IDE也允许您重构字符串(重命名字段时)。您只需要确保随后将这些信息传播到整个团队(以及将来的成员)即可。


使用反射的先前答案:

如果使用动态,是指它必须以该名称开头或包含该名称,则可能需要使用以下内容,即getDeclaredFields()并对其进行迭代以过滤出感兴趣的字段:

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
}

如果您需要按类型或注释等进行过滤,则此示例就足够了。只需对过滤器进行相应调整即可。

如果只是您需要的字段名称,那么它就是您想要的Field.getName()

答案 1 :(得分:2)

 private static String getCustom(RequestDto requestDto) throws NoSuchFieldException, IllegalAccessException {
    Field field = requestDto.getClass().getDeclaredField("custom");
    field.setAccessible(true);
    return (String) field.get(requestDto);
}

如果它对您来说不够“动态”:

private static String getField(RequestDto requestDto, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Field field = requestDto.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        return (String) field.get(requestDto);
    }