Основной синтаксис

Определение имени пакета

Имя пакета указывается в начале исходного файла, так же как и в Java:

package my.demo

import java.util.*

// ...

Но в отличие от Java, нет необходимости, чтобы стуктура пакетов совпадала со структурой папок: исходные файлы могут располагаться в произвольном месте на диске.

См. Пакеты.

Объявление функции

Функция принимает два аргумента Int и возвращает Int:

fun sum(a: Int, b: Int): Int {
  return a + b
}

Функция с выражением в качестве тела и автоматически выведенным типом возвращаемого значения:

fun sum(a: Int, b: Int) = a + b

Функция, не возвращающая никакого значения (void в Java):

fun printSum(a: Int, b: Int): Unit {
  print(a + b)
}

Тип возвращаемого значения Unit может быть опущен:

fun printSum(a: Int, b: Int) {
  print(a + b)
}

См. Функции.

Определение внутренних переменных

Неизменяемая (только для чтения) внутренняя переменная:

val a: Int = 1
val b = 1   // Тип `Int` выведен автоматически
val c: Int  // Тип обязателен, когда значение не инициализируется
c = 1       // последующее присвоение

Изменяемая переменная:

var x = 5 // Тип `Int` выведен автоматически
x += 1

См. Свойства и поля.

Использование строковых шаблонов

Допустимо использование переменных внутри строк в формате $name или ${name}:

fun main(args: Array<String>) {
  if (args.size == 0) return

  print("First argument: ${args[0]}")
}

См. Строковые шаблоны.

Использование условных выражений

fun max(a: Int, b: Int): Int {
  if (a > b)
    return a
  else
    return b
}

Также if может быть использовано как выражение (т. е. if ... else возвращает значение):

fun max(a: Int, b: Int) = if (a > b) a else b

См. Выражение if.

Nullable-значения и проверка на null

Ссылка должна быть явно объявлена как nullable (символ ?) когда она может принимать значение null.

Возвращает null если str не содержит числа:

fun parseInt(str: String): Int? {
  // ...
}

Использование функции, возвращающей null:

fun main(args: Array<String>) {
  if (args.size < 2) {
    print("Ожидается два целых числа")
    return
  }

  val x = parseInt(args[0])
  val y = parseInt(args[1])

  // Использование `x * y` приведет к ошибке, потомучто они могут содержать null
  if (x != null && y != null) {
    // x и y автоматически приведены к не-nullable после проверки на null
    print(x * y)
  }
}

или

  // ...
  if (x == null) {
    print("Неверный формат числа у '${args[0]}'")
    return
  }
  if (y == null) {
    print("Неверный формат числа у '${args[1]}'")
    return
  }

  // x и y автоматически приведены к не-nullable после проверки на null
  print(x * y)

См. Null-безопасность.

Проверка типа и автоматическое приведение типов

Оператор is проверяет, является ли выражение экземпляром заданного типа. Если неизменяемя внутренняя переменная или свойство уже проверены на определенный тип, то в дальнейшем нет небходимости явно приводить к этому типу:

fun getStringLength(obj: Any): Int? {
  if (obj is String) {
    // `obj` is automatically cast to `String` in this branch
    return obj.length
  }

  // `obj` is still of type `Any` outside of the type-checked branch
  return null
}

или

fun getStringLength(obj: Any): Int? {
  if (obj !is String)
    return null

  // `obj` is automatically cast to `String` in this branch
  return obj.length
}

или даже

fun getStringLength(obj: Any): Int? {
  // `obj` is automatically cast to `String` on the right-hand side of `&&`
  if (obj is String && obj.length > 0)
    return obj.length

  return null
}

См. Классы и Приведение типов.

Использование цикла for

fun main(args: Array<String>) {
  for (arg in args)
    print(arg)
}

или

for (i in args.indices)
  print(args[i])

См. цикл for.

Использование цикла while

fun main(args: Array<String>) {
  var i = 0
  while (i < args.size)
    print(args[i++])
}

См. цикл while.

Использование выражения when

fun cases(obj: Any) {
  when (obj) {
    1          -> print("One")
    "Hello"    -> print("Greeting")
    is Long    -> print("Long")
    !is String -> print("Not a string")
    else       -> print("Unknown")
  }
}

См. выражение when.

Использование диапазонов

Проверка входит ли число в диапазон с помощью оператора in:

if (x in 1..y-1)
  print("OK")

Проверка числа на выход из диапазона:

if (x !in 0..array.lastIndex)
  print("Out")

Проход по диапазону:

for (x in 1..5)
  print(x)

См. Диапазоны.

Использование коллекций

Итерация по коллекции:

for (name in names)
  println(name)

Проверка содержит ли коллекция данный объект с помощью оператора in:

if (text in names) // names.contains(text) is called
  print("Yes")

Используем лямбда-выражения для фильтрации и модификации коллекции:

names
    .filter { it.startsWith("A") }
    .sortedBy { it }
    .map { it.toUpperCase() }
    .forEach { print(it) }

См. Функции высшего порядка и лямбды.