На уровне Kotlin все просто:
val x = 10
var y = 20
y = 30 // компилятор разрешает
x = 30 // компилятор запрещает
Если глянуть глубже, на уровне JVM, то там ничего подобного вообще нет:
class Dessert {
val name = "Cake" // превратится в private final String name с getName() методом
var count = 0 // превратится в private int count c getCount() и setCount() методами
}Ключевое слово final запрещает полю присваивать новое значение, это проверка реализована на уровне верификатора JVM, специальный компонент JVM который проверяет корректность команд байт-кода, очень важная штука для безопасного выполнения кода.
Локальные переменные проверяются только на уровне Kotlin компилятора:
val x = 10 // В JVM байт-коде разрешены записи в такую переменную, но Kotlin компилятор не сгенерирует такой байт-код
C лямбдами поинтереснее:
var dessert = Dessert() // создается обертка ObjectRef, которая внутри хранит объект как element поле
val lambda = {
// под капотом будет objectRef.element = Dessert()
dessert = Dessert()
}
При создании лямбды ссылка на объект копируется, а это значит если в
dessert присвоить другой объект, у лямбды будет ссылка на старый, поэтому var переменные оборачиваются в специальные классы ObjectRef, IntRef и тд.Ну и вообще проверки Kotlin компилятора и JVM верификатора не означают что val переменные / поля нельзя изменить, всегда есть механизм рефлексии и вызов Си / C++ кода через JNI.
