Comments 19
Спасибо за статью!
Вышло, даже, немного забавнее, похоже и вправду баг.
TestA компилируется, TestB — нет. Если верить просмотрщику байткода в IDE, байткод генерируется одинаковый.
Может, стоит зарепортить на youtrack.jetbrains.net/issues/KT?
Получается, что поле, объявленное как val, поменяло значение в процессе исполнения кода. Почему так? Думаю, что это недочёт компилятора Kotlin, и в будущем, возможно, такое не скомпилируется, но на сегодняшний день всё так, как есть.
Вышло, даже, немного забавнее, похоже и вправду баг.
class TestA {
constructor()
init {
immutableString = "44"
}
val immutableString = "42"
}
class TestB() {
init {
immutableString = "44"
}
val immutableString = "42"
}
TestA компилируется, TestB — нет. Если верить просмотрщику байткода в IDE, байткод генерируется одинаковый.
Может, стоит зарепортить на youtrack.jetbrains.net/issues/KT?
+2
Случай и правда любопытный — зарепортил его. Может получу какие либо пряснения к данному конкретному случаю. Но скорее всего это проблема и ее надо вылечить
+1
Замечу также, что результатом будет первичное присвоение. То есть, код в блоке инициализации просто не выполняется.
0
Это не так. Из блока инициализации мы вызываем метод showTestParam(), который использует значение testParam, присвоенное ему в блоке init. Вывод логов мы видим. Так что вся логика init блока отрабатывает
0
Точно, сам в этом убедился. Определенно это какой-то баг.
Даже еще интереснее!
Не компилируется!
Даже еще интереснее!
class ThreadTest {
constructor() {
println("c1")
}
init {
println("init_start, $bul")
bul = false
println("init_end")
}
val bul: Boolean = true
}
Не компилируется!
0
Если исследовать порядок выполнения, то видим, что код выполняется сверху вниз
Результат:
init_start
assign1
init_end
assign2
constructor
2
fun main(args: Array<String>) {
val a = ThreadTest()
println(a.bul)
}
class ThreadTest {
constructor() {
println("constructor")
}
init {
println("init_start")
bul = f1()
println("init_end")
}
private fun f1(): Int {
println("assign1")
return 3
}
val bul = f2()
private fun f2(): Any {
println("assign2")
return 2
}
}
Результат:
init_start
assign1
init_end
assign2
constructor
2
0
более того, если байт код того, что компилится мы преобразуем в java код, то компилятор на этот код будет ругаться. И еще: если в этих котлиновских классах объявление val поля сделать до init блока, то компилятор ругаться будет
0
Причем в этом коде оба присвоения будут в конструкторе. Но по факту срабатывать будет только последнее. Каким образом компилятор вымарывает первое срабатывание — большой вопрос.
И еще огромный вопрос вот в чем — а не может ли такого быть, что переменная объявляется фактически не финальной? Или финальная переменная действительно каким-то образом переписывается (хотя в JSR 133 это вроде невозможно)
То есть, могу ли я, имея несколько потоков, ухитриться получить одним из потоков первое значение вместо второго?
И еще огромный вопрос вот в чем — а не может ли такого быть, что переменная объявляется фактически не финальной? Или финальная переменная действительно каким-то образом переписывается (хотя в JSR 133 это вроде невозможно)
То есть, могу ли я, имея несколько потоков, ухитриться получить одним из потоков первое значение вместо второго?
0
Если смотреть на этот процесс как бы снаружи, то здесь единственное отличие от Java — отсутствие ключевого слова new при вызове конструктора.
Можно вспомнить про возможность передавать именованные параметры в конструкторы и функции. Полезно если несколько параметров опциональные и нужно передать значение для 2 или 3го (например какой-нибудь вызов joinToString(prefix = "")). Taк же может помочь в ревью, когда в метод\конструктор передаются однотипные данные а подсказок студии нет(к примеру пачка true\false)
class User(val name: String, val age: Int)
// порядок передачи параметров уже не важен
val mike = User(age = 25, name = "Mike")
+2
Присоединяюсь — очень ценная статья для начинающих в Kotlin. Ждем продолжения.
Подскажите, а в вашей компании — FunCorp — насколько активно используется Kotlin?
+1
С интересом прочитал, хоть ничего нового и не узнал. Буду ждать новые статьи.
Думаю, стоило бы упомянуть, что при использовании @JvmOverloads компилятор создаёт набор конструкторов с разным количеством аргументов.
Думаю, стоило бы упомянуть, что при использовании @JvmOverloads компилятор создаёт набор конструкторов с разным количеством аргументов.
+1
Такого рода статьи значительно облегчают переход на Kotlin.
Спасибо Вам за статью.
Давайте сразу копать Kotlin во все стороны! Отдыхать не обязательно.
Спасибо Вам за статью.
Давайте сразу копать Kotlin во все стороны! Отдыхать не обязательно.
+2
Хорошая статья! Ждём продолжения!
+1
Стоило упомянуть, что в Kotlin нет свойств, а только поля. Это имеет прямое отношение к val
и var
параметрам первичного конструктора.
0
Sign up to leave a comment.
Kotlin: копаем глубже. Конструкторы и инициализаторы