Skip to content
Advertisement

Is there a Lombok way to initialise a final field that is calculated from other fields?

I’m using Lombok to minimize code. Here’s my (contrived) situation in vanilla Java:

public class MyClass {
    private final int x;
    private final int sqrt;
    public MyClass(int x) {
        this.x = x;
        sqrt = (int)Math.sqrt(x);
    }
    // getters, etc
}

I want to use lombok to generate the constructor and getters:

@Getter
@RequiredArgsConstructor
public class MyClass {
    private final int x;
    private int sqrt;
}

To get the computation into the class, you might consider an instance block:

{
    sqrt = (int)Math.sqrt(x);
}

but instance blocks are executed before code in the constructor executes, so x won’t be initialized yet.

Is there a way to execute sqrt = (int)Math.sqrt(x); after x is assigned with the constructor argument, but still use the constructor generated by RequiredArgsConstructor?

Notes:

  • Coding the computation in the getter is not an option (for one, it negates the benefit of using @Getter)
  • This example is a gross simplification of the real life class, which has many final fields, and several computed/derived fields, so the boilerplate savings using lombok are considerable
  • The class is a simple POJO DTO, not a managed bean, so none of the lifecycle javax annotations (e.g. @PostConstruct) are of any use

Advertisement

Answer

How about using the lazy option on @Getter for the computation:

// tested and works OK
@Getter(lazy = true) 
private final int sqrt = (int) Math.sqrt(x);

Note: Calling getSqrt() works as expected/hoped, firing the computation and setting the “final” field, however accessing the field directly does not invoke the magic – you get the uninitialized value.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement