Published on

Lazy Initializing Variables in Kotlin

Authors

One of the things I really love about Kotlin is how the language is designed with lots of little syntactic sugar which makes my life as a developer much easier. For example today I was working on a Spring Component that had two parameters constructor injected in - one of these was optional (using Kotlin's default parameter feature). The none-default of these two parameters was Autowired in but the problem with this approach is that Spring does not know how to build this bean. I needed this other parameter to be optional so that something could be used as part of constructing an object in this class but I wanted that object to be immutable.

The way I would handle this in Java is let the optional parameter be setter injected into the class and lazy initialize the object I need inside the class:

@Component
public class MyService {
    private final SomeProperties someProperties;
    private SomeService someService;
    private List<SomeHelper> listOfOptionalHelpers = new LinkedList<>;

    @Autowired
    public MyService(SomeProperties someProperties){
        this.someProperties = someProperties;
    }

    public void setListOfOptionalHelpers(List<SomeHelper> listOfOptionalHelpers) {
        this.listOfOptionalHelpers = listOfOptionalHelpers;
    }

    private SomeService lazyInitializeSomeService(){
        if(someService == null) {
            someService = new SomeService(someProperties , listOfOptionalHelpers);
        }
        return someService;
    }
    ...
}

As you can see even in the Java approach I am forced to make SomeService mutable when ideally it should be immutable. Luckily Kotlin has made lazy initializing objects much easier which also has the added benefit of being able to define this lazy object inline and make it immutable:

@Component
class MyService(@Autowired someProperties: SomeProperties) {

    var listOfOptionalHelpers: List<SomeHelper> = listOf()

    private val someService: SomeService by lazy {
        SomeService(someProperties , listOfOptionalHelpers)
    }
    ...
}

As lazy is a function that takes a lambda the last thing returned in it is what is returned by the lambda and what Kotlin will initialize the object to. As this is lazy this will only initialize once whereafter the value that has already been initialized will be returned again on subsequent calls to someService.