val - не может быть переназначена, т.е. неизменяемая (но не путать с const val)
var - может быть переназначена, т.е. можно изменять значения и перезаписывать
const val - константа, которая не изменяются во время выполнения программы и доступны из разных частей кода. В них можно хранить, например, какой-нибудь URL внутри приложения или его версию.
Целочисленные типы
Вещественные типы (числа с плавающей точкой)
Символьные и строковые типы
Логический
val a = 10 // целочисленный тип переменной присвоится автоматически
val b: Int = 3 // принудительно указываем тип переменной Int
println(10 / 3) // вывод результата в консоль. Покажет 3, т.к. целочисленный тип
println(10 % 3) // показать остаток от деления
val с: Float = 10f // тип переменной Float (32 бита)
val d: Float = 3f
println(с / d) // результат: 3.3333333
val e: Double = 10.0 // тип переменной Double (64 бита)
val f: Double = 3.0
println(e / f) // результат: 3.3333333333333335
println(f::class.simpleName) // узнать тип переменной f, результат: double
.. - увеличение чисел в диапазоне
until - увеличение чисел в диапазоне не включая последнее число
downTo - уменьшение чисел в диапазоне
val range0 = 2..12 // диапазон от 2 до 12 включительно
val range1 = 2 until 12 // диапазон от 2 до 12, не включая 12
val range2 = 10 downTo 1 // диапазон от 10 до 1
// Диапазоны могут быть определенных типов:
val range3 = 2L..12L // Long
val range4 = 'a'..'z' // Char
val range5 = 2.1..12.1 // Double
val range6 = 2.1f..12.1f // Float
// Или принудительно объявляем:
val range1: IntRange = 2 until 12
val range2: IntRange = 2..12
val range3: LongRange = 2L..12L
val range4: CharRange = 'a'..'z'
val range5: ClosedRange<Double> = 2.1..12.1
val range6: ClosedRange<Float> = 2.1f..12.1f
Прогрессия или диапазон увеличивающихся/уменьшающихся чисел с шагом step. По умолчанию step всегда равен 1. У прогрессии есть свои типы, например, IntProgression, CharProgression и т.д.
val range7 = 2 .. 12 step 2 // диапазон с 2 до 12 включительно с шагом 2 или:
val range7: IntProgression = 2 .. 12 step 2
val range8: IntProgression = 12 downTo 2 step 2 // диапазон с 12 до 2 с шагом 2
val a = 10 in range1
val b = 20 !in range1
println(a) // результат: true (истина, принадлежит диапазону)
println(b) // результат: true (истина, т.к. не принадлежит диапазону)
Прибавлять единицу можно несколькими способами (все эти операторы делают одно и то же):
Отнять единицу:
В таком виде могут понадобиться, когда, например, нужно сначала увеличить/уменьшить значение на единицу, а затем использовать его.
println(a > b) // больше
println(a < b) // меньше
println(a >= b) // больше или равно
println(a <= b) // меньше или равно
println(a == b) // == равно
println(a != b) // != не равно
Вернемся к циклам. В прошлом уроке мы делали обратный отсчет с распечаткой значения в консоль каждую секунду с помощью цикла while и do-while. Сейчас я хочу познакомить вас с новым видом цикла – for. И, на самом деле, он более подходит для реализации задачи с обратным отсчетом, как вы могли уже догадаться.
Сначала вопрос: как определить в каких случаях использовать while, а когда for? Если известно какое количество итераций цикла нужно совершить, то следует использовать for. Если количество заранее не известно или условие меняется по ходу сценария программы – тогда рекомендуется while (или do-while).
Нам точно известно, что количество итераций для программы отбратного отсчета равно количеству заданных секунд – в нашем случае это 5. И давайте реализуем это более корректно, используя цикл for. Его преимущества будут наглядно продемонстрированы на следующем примере.
for (i in 5 downTo 1) {
println("Реклама закончится через $i")
Thread.sleep(1000)
}
Пишем ключевое слово for. В круглых скобках будет условие (как и где нужно совершать перебор значений). Тело цикла расположено в фигурных скобках. Скопируем его из while с прошлого урока. В теле мы печатаем значение из списка или диапазона и ждем одну секунду. Теперь разберем новый синтаксис условия.
i – переменная, которая создается в рамках текущего цикла. Она будет служить контейнером для текущего элемента из предоставляемого списка, которое мы распечатываем. Название может быть произвольным. Как видите, мы уже не используем никаких дополнительных вспомогательных переменных вне счетчика (как это было в while).
5 downTo 1 – в этом месте условия записывается некая коллекция. Список, массив или диапазон чисел, который будет перебирать цикл. В данном случае с помощью downTo мы создали диапазон чисел (что является прогрессией) со значениями в порядке убывания. downTo означает, что значение переменной i в цикле for уменьшается на 1 на каждом шаге цикла. При подстановке диапазона в порядке возрастания, объявленного через точки (..) или until, значение i в цикле for будет увеличиваться на 1 на каждом шаге цикла.
Запускаем и видим корректно отрабатывающий обратный отсчет.
Помним, что шаг прохода (step) по умолчанию 1. Создадим еще один цикл для примера, подставим один из созданных выше диапазонов и укажем step 8.
for (i in range2 step 8) {
println(i)
}
Отлично. Бывают ситуации, когда цикл не нужно отрабатывать до конца. Например, если мы нашли искомое значение. В этом случае продолжать перебор дальше бессмысленно, так как это пустая трата ресурсов. Тогда мы должны прервать цикл и выйти из него. Сделать это можно с помощью операторов перехода. Их будет три: break, continue и return.
Представим, что в нашем обратном отсчете показа рекламы есть кнопка “Пропустить”. И представим, что пользователь нажал на нее за 3 секунды до конца показа рекламы. Ни о каких перехватах нажатий сейчас не беспокоимся, просто воспринимаем это как факт. Задача сейчас состоит в том, чтобы за 3 секунды до конца отсчета закрыть рекламу и остановить счетчик. Напишем этот пример:
for (i in 5 downTo 1) {
if(i == 3) {
println("Пользователь нажад на кнопку \\"Пропустить\\"")
break
}
println("Реклама закончится через $i")
Thread.sleep(1000)
}
Что тут происходит. На каждой итерации цикла мы делаем проверку. Равно ли значение переменной 3. Если значение не равно, мы не заходим в условие if. Если значение равно, заходим в условие, печатаем информацию о том, что предполагаемый пользователь нажал на кнопку «Пропустить» и вызываем оператор break. Этот оператор завершит работу цикла полностью. Программа продолжить работать, если ниже после цикла будут дополнительные инструкции. Для наглядности добавим сообщение после цикла, это пригодится нам немного позже:
println("Продолжение работы программы вне цикла")
Кстати, вы можете обратить внимание на особое закавычивание слова “Пропустить”. Здесь мы применили так называемое экранирование символов. Экранирование – это замена в тексте управляющих символов на соответствующие текстовые подстановки. Я не могу написать несколько кавычек подряд. Это будет воспринято как окончание строки, что вызовет ошибку. Обратный слэш перед нужным символом превратит его в функциональный смысл в строчное значение.
Теперь про оператор continue. При применении этого оператора мы можем прервать текущую итерацию. Это может понадобиться тогда, когда мы нашли искомое значение, что-то с ним сделали, и не хотим, чтобы исполнялись дальнейшие инструкции в теле цикла в текущей итерации. При этом работа цикла не заканчивается, а только лишь прерывается текущий круг. Для демонстрации модифицируем наш пример:
for (i in 5 downTo 1) {
if(i == 3) {
// println("Пользователь нажал на кнопку \\"Пропустить\\"")
// break
println("i == 3, i не будет распечатана")
continue
}
println("Реклама закончится через $i")
Thread.sleep(1000)
}
Вывод в консоль
Реклама закончится через 5
Реклама закончится через 4
i == 3, i не будет распечатана
Реклама закончится через 2
Реклама закончится через 1
В этом случае, когда значение i становится 3 – заходим в условие, печатаем информационное сообщение и вызываем continue. Цикл прерывается, не распечатав сообщение с рекламным счетчиком и начинается новый круг.
Наконец, оператор перехода return. В этом случае программа завершает выполнение функции в которой она находится. В нашем случае это метод main(). То есть в текущих условиях мы полностью остановим выполнение программы, так как у нас запущена одна единственная исполняемая функция main(). Еще раз модифицируем пример:
for (i in 5 downTo 1) {
if(i == 3) {
// println("Пользователь нажад на кнопку \\"Пропустить\\"")
// break
// println("i == 3, i не будет распечатана")
// continue
return
}
println("Реклама закончится через $i")
Thread.sleep(1000)
}
Вывод в консоль
Реклама закончится через 5
Реклама закончится через 4
В этом случае, как только значение i становится 3 – вызовется оператор return и программа завершит свое выполнение. Это можно заметить по отсутствию сообщения “Продолжение работы программы вне цикла”, которое мы печатали ниже по ходу программы.