What 'final' keyword next to the field stands for?

Viewed 179

In a legacy code, I'm working with, I found the following thing:

@Autowired
final lateinit var controller: CustomController

what does this final keyword mean here?

In a Kotlin documentation I found a short description about final keyword that is blocking overriding of the methods in open classes but no information about fields. Also - the class within which I found the line is not open

2 Answers

A final property or a method in Kotlin prevents overriding of the field / method. That being said, Kotlin by default considers a property or a method/function to be final unless specified by the keyword open. In your case, the final keyword is redundant.

Here's a small demo test case to illustrate the same.

open class Parent {
    open val someValue = 0
    final val otherValue = 13 // redundant modifier 'final' warning in Android Studio
}

class Child : Parent() {
    override val someValue = 5
    // override val otherValue = 19 // compile error
}

There is an interesting problem called Fragile Base Class in OOP and why some languages like Kotlin prefer final by default.

What you have there is a property, not a field.

It looks just like a field, as it would in Java; but in Kotlin, it actually defines a public getter method, a public setter method, and a private backing field*.

So the final modifier applies to the accessor methods, preventing those from being overridden in a subclass.  (As you say, the backing field itself can't be overridden anyway.)

As Siddharth says, final is the default in Kotlin, so you usually wouldn't need to specify it, though there are a few situations in which it would be needed — e.g. if it were already overriding something, or you were using the all-open or kotlin-spring compiler plug-ins.  (The use of @Autowired suggests that this is a Spring module, which probably explains why final is needed here.)  In any case, your IDE would probably indicate where it's not needed, e.g. by showing it greyed-out.

(* Only the getter is necessary; the setter isn't generated for a val, and the backing field isn't generated if you override the accessor(s) and they don't refer to it.)

Related