-1

I have a large monthly summary object with lots of fields. When creating a new one, I need to calculate the amount / percent diff for each field from the previous month, something like so:

public Summary addSummary(Summary current) {
   Summary previous = getPreviousSummary(getPreviousMonth();

   current.setPropertyA(NumUtil.getFormattedValue(current.getPropertyA(), previous.getPropertyA()));
   // repeat 80 more times

   ...
}

currently I'm doing it manually, which is tedious and super ugly, is there a way to loop through all the properties / set them after running them through a function?

I did some searching and BeanUtils can copy properties, but not transform them.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Mankind1023
  • 7,198
  • 16
  • 56
  • 86
  • 3
    Does this answer your question? [What is reflection and why is it useful?](https://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful) – maio290 Jul 22 '21 at 17:41
  • Is `mapstruct` an option? It has some data type conversion and formatting support. https://mapstruct.org/documentation/stable/reference/html/#datatype-conversions – aksappy Jul 22 '21 at 18:06
  • Are all the properties the same type? – Andreas Jul 22 '21 at 18:06
  • 1
    You have no problem with writing 80 getter/setter pairs for your 80 properties, but a problem writing 80 lines of "format value"? Why? – Andreas Jul 22 '21 at 18:08
  • I use lombok so the class files are much cleaner :D – Mankind1023 Jul 22 '21 at 18:17

1 Answers1

3

You can use reflection to solve your problem. As I don't know actually what you're gonna get and set from those two objects, I am giving a minimal example to show what you can do in this case.

You can get all the declared fields in your Summary class as follows:

Field[] arrayOfFields = Summary.class.getDeclaredFields();

As you have all the fields of the class summary, you can iterate through each field and do the get and set easily for different objects of that class as follows. Remember to set field.setAccessible(true) if the fields are private inside the class:

for (Field field: arrayOfFields) {
    try {
        field.setAccessible(true);
        if (field.getType() == Double.class) {
            Double prevVal = field.get(previous);
            Double currentVal = field.get(current);
            //do calculation and store to someval
            field.set(resultSummary, someval);
        }
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

Well, you may need to check all type of classes that your class Summary has and do the get and set according to that type. Please keep in mind that you cannot use primitive type fields for this if condition check as they are not Class. So, you may need to convert the primitive type variables in the summary class to corresponding Object Class. Like double to Double etc.

The field.get(Object obj) method gets the value for the field in the Object obj. Similarly, field.set(Object obj, Object value) sets the Object value to the field in the Object obj

With this approach you can achieve the goal easily with less hassle and dynamic coding.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
devReddit
  • 2,696
  • 1
  • 5
  • 20