java reflection get specific declared field value as String

Lokeshkumar R :

I am having a declared field in RequestDto as (requestDto has many declared field but i want only this custom field)

private String custom; 

i wanted to get this declared field name Custom as String

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

The solution has to be without modifying default getters and setters

Actually i have a problem like when a requestDto is processed for content validation if one of the field in the request Dto is having an bad data i should provide an error message along with the field name as string which had an irrelevant data

The problem is when custom field is modified in RequestDto in future ,the person modifying it will not even be knowing that custom field is set as string and it is used ,so i wanted to have the custom field name as string from RequestDto only ,so when ever the field value is changed i get the changed name in string

Roland :

Edit: after you have added the most important piece of information in the comment "what if someone changes that name in the future"... well... then reflection is not the way to go!

I would then rather use something like a Function<RequestDto, String> or similar instead, e.g.:

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

and call it via:

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

If that field is refactored in future that part will be refactored too then automatically (well... depends on your IDE probably ;-)). But... it will not give you the appropriate field name as error message. Note that there isn't a nice way to catch the right field, if the only property to get it, is its name. If you would put an annotation to the field, you could then filter and grab the field with that specific annotation. That way you do not need to know the actual name... but counterquestion: how can you be sure that only 1 field is annoted with that annotation? I would rather redesign that specific part of your application. I wouldn't expose any field to the "client". If that means that I have potentially different names in the error message and the field names, so be it.

Note also that modern IDEs allow you to refactor strings as well (when you rename a field). You just need to ensure that this information is spread across the team then (and also future members).


Previous answer using reflection:

If with dynamic you mean, that it must start with that name or contain that name, you may want to use something as follows, i.e. getDeclaredFields() and iterate over them to filter out interested fields:

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
}

This sample should suffice in case you need to filter by type or by annotation, etc. Just adapt the filter then accordingly.

If it's just the name of a field that you require, it is Field.getName() what you want.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=88944&siteId=1