Kotlin has a nice and very useful feature called delegated properties. This allows software engineers to add special behavior around a property. For example with the lazy delegate you can delay the calculation of the field. This may be useful if the calculation is expensive and the calculated value can be re-used multiple times.
The standard library comes with a very modest set of delegates, and to be honest other than the lazy, I haven't found them really useful, but I wrote a couple of delegates that I have found good use of, let's begin with...
Java comes with quite a few utility classes, which we in many cases would like to have as a constant and share it between all threads of the code, until we find that ohhh... surprisingly, they are not thread safe. Probably the most common ones are:
SimpleDateFormat is indeed the fastest way of parsing date and times and formatting string from Date objects, but it is absolutely not thead-safe, therefore you may be making a billion dollar mistake if you share them as static final.
- All of the traditional XML processing APIs: DOM, XPath, etc...
Quite annoying, because they are also very expensive to initialize. I wonder what was the design idea... but anyway
The simple solution is: you do not share them, you do not reuse them, each time you need such an object, you produce one your code refers to it just as local variable, you leave it to the garbage collector after processing.
This will be safe, but a bit slow... or kind of slow if you need to do this a lot.
There is a more performant solution: you declare a ThreadLocal.
Now it is safe for multiple threads, but doesn't look pretty does it? No, it looks crap.
Let's see what can kotlin do for us:
Doesn't this look a lot more human-readable? And just as safe as the java counterpart.
weakWeak is almost like lazy. It is actually lazy, because the expression will be evaluated at first use. The difference is that reference to the stored value will be weak and therefore whenever the JVM is running low on memory the garbage collector is free to throw them away. Once the results of the calculations are dropped, they will be recalculated again when needed, therefore we balance between good performance and memory limits.
I have found this very useful when working with large data-structures. Of course it is a little bit slower when accessing the stored value compared to the lazy delegate, that is the overhead of using and checking the weak reference.
Give it a try, tell me what you think
The delegates are packaged in kroki-delegates package and deployed in maven central and the code is shared on github.
Use it for good, never for evil.