- Kotlin language specification
- Lexical grammar
- Whitespace and comments
- Keywords and operators
- Literals
- Identifiers
- String mode grammar
- Tokens
- Syntax grammar
- Основной синтаксис
- Определение имени пакета и импорт
- Точка входа в программу
- Вывод в стандартный поток
- Функции
- Переменные
- Создание классов и экземпляров
- Комментарии
- Строковые шаблоны
- Условные выражения
- Цикл for
- Цикл while
- Выражение when
- Интервалы
- Коллекции
- Nullable-значения и проверка на null
- Проверка типа и автоматическое приведение типов
- Basic syntax
- Package definition and imports
- Program entry point
- Print to the standard output
- Functions
- Variables
- Creating classes and instances
- Comments
- String templates
- Conditional expressions
Kotlin language specification
This section uses a BNF-based notation similar to EBNF with the following conventions:
- Any sequence of characters given in single-quotes and monospace font denote a terminal sequence;
- Special terminal sequences that needs specification are given in angle brackets: ;
- Normal parentheses are used sparingly to specify priority between other operations;
- A sequence of rules A and B: (A B);
- Choice between rules A and B: (A | B);
- Optional use of rule A: [A];
- Repetition of rule A: .
Rule names starting with capital letters denote lexical rules, while rule names starting with lowercase letters denote syntactic rules.
Note: this notation is similar to ISO EBNF as per standard ISO/IEC 14977, but does not employ any special symbols for concatenation or termination and does not use some of the additional notation symbols
Lexical grammar
Whitespace and comments
Keywords and operators
Literals
Identifiers
Kotlin supports escaping identifiers by enclosing any sequence of characters into backtick ( ` ) characters, allowing to use any name as an identifier. This allows not only using non-alphanumeric characters (like @ or # ) in names, but also using keywords like if or when as identifiers. Actual set of characters that is allowed to be escaped may, however, be a subject to platform restrictions. Consult particular platform sections for details.
Note: for example, the following characters are not allowed in identifiers used as declaration names on the JVM platform even when escaped due to JVM restrictions: . , ; , [ , ] , / , < , >, : , \\ .
Escaped identifiers are treated the same as corresponding non-escaped identifier if it is allowed. For example, an escaped identifier `foo` and non-escaped identifier foo may be used interchangeably and refer to the same program entity.
Some of the keywords used in Kotlin are allowed to be used as identifiers even when not escaped. Such keywords are called soft keywords. You can see the complete list of soft keyword in the rule above. All other keywords are considered hard keywords and may only be used as identifiers if escaped.
Note: for example, this is a valid property declaration in Kotlin:
even though field is a keyword
String mode grammar
Opening a double quote (QUOTE_OPEN) rule puts the lexical grammar into the special “line string” mode with the following rules. Closing double quote (QUOTE_CLOSE) rule exits this mode.
Opening a triple double quote (TRIPLE_QUOTE_OPEN) rule puts the lexical grammar into the special “multiline string” mode with the following rules. Closing triple double quote (TRIPLE_QUOTE_CLOSE) rule exits this mode.
Tokens
These are all the valid tokens in one rule. Note that syntax grammar ignores tokens DelimitedComment, LineComment and WS.
Syntax grammar
The grammar below replaces some lexical grammar rules with explicit literals (where such replacement in trivial and always correct, for example, for keywords) for better readability.
Основной синтаксис
Это подборка базового синтаксиса с примерами. В конце каждого раздела вы найдете ссылку на более подробное описание соответствующей темы.
Вы также можете изучить все основы Kotlin в бесплатном курсе Основы Kotlin от JetBrains Academy.
Определение имени пакета и импорт
Имя пакета указывается в начале исходного файла, так же как и в Java.
package my.demo import java.util.* // .
Но в отличие от Java, нет необходимости, чтобы структура пакетов совпадала со структурой папок: исходные файлы могут располагаться в произвольном месте на диске.
Точка входа в программу
В Kotlin точкой входа в программу является функция main .
Другая форма main может принимать массив строк String .
Вывод в стандартный поток
print выводит свой аргумент в стандартный поток вывода.
println выводит свой аргумент и добавляет перевод строки, так что следующее, что вы выведите, появится на следующей строке.
println("Hello world!") println(42)
Функции
Функция принимает два аргумента Int и возвращает Int .
В качестве тела функции может выступать выражение. Тогда тип возвращаемого значения определяется автоматически.
Функция, не возвращающая никакого значения ( void в Java).
fun printSum(a: Int, b: Int): Unit < println("сумма $a и $b равна $") >
Тип возвращаемого значения Unit может быть опущен.
Переменные
Неизменяемые (только для чтения) локальные переменные определяются с помощью ключевого слова val . Присвоить им значение можно только один раз.
val a: Int = 1 // Инициализация при объявлении val b = 1 // Тип `Int` определен автоматически val c: Int // Указывать тип обязательно, если переменная не инициализирована сразу c = 1 // Последующее присвоение
Изменяемые переменные объявляются с помощью ключевого слова var .
var x = 5 // Тип `Int` определен автоматически x += 1
Вы можете объявлять глобальные переменные.
val PI = 3.14 var x = 0 fun incrementX()
Создание классов и экземпляров
Для создания класса используйте ключевое слово class .
Свойства класса могут быть перечислены при его объявлении или в его теле.
class Rectangle(var height: Double, var length: Double)
Конструктор по умолчанию с параметрами, перечисленными при объявлении класса, доступен автоматически.
val rectangle = Rectangle(5.0, 2.0) println("Периметр равен $")
Чтобы объявить наследование между классами используйте двоеточие ( : ). По умолчанию классы являются финальными, поэтому, чтобы сделать класс наследуемым, используйте open .
open class Shape class Rectangle(var height: Double, var length: Double): Shape()
Комментарии
Также, как любой другой популярный современный язык, Kotlin поддерживает однострочные и многострочные (блочные) комментарии.
// Это однострочный комментарий /* Это блочный комментарий из нескольких строк. */
Блочные комментарии в Kotlin могут быть вложенными.
/* Этот комментарий начинается здесь /* содержит вложенный комментарий */ и заканчивается здесь. */
См. Документация Kotlin кода для информации о документации в комментариях.
Строковые шаблоны
Допустимо использование переменных внутри строк в формате $name или $ :
var a = 1 // просто имя переменной в шаблоне: val s1 = "a равно $a" a = 2 // произвольное выражение в шаблоне: val s2 = "$, но теперь равно $a" /* Результат работы программы: a было равно 1, но теперь равно 2 */
Условные выражения
fun maxOf(a: Int, b: Int): Int < if (a >b) < return a >else < return b >>
В Kotlin if может быть использован как выражение (т. е. if . else возвращает значение):
fun maxOf(a: Int, b: Int) = if (a > b) a else b
Цикл for
val items = listOf("яблоко", "банан", "киви") for (item in items)
val items = listOf("яблоко", "банан", "киви") for (index in items.indices) < println("$фрукт - это $") >
Цикл while
val items = listOf("яблоко", "банан", "киви") var index = 0 while (index < items.size) < println("$фрукт - это $") index++ >
Выражение when
fun describe(obj: Any): String = when (obj) < 1 ->"Один" "Hello" -> "Приветствие" is Long -> "Long" !is String -> "Не строка" else -> "Unknown" >
Интервалы
Проверка на вхождение числа в интервал с помощью оператора in .
val x = 10 val y = 9 if (x in 1..y+1)
Проверка значения на выход за пределы интервала.
val list = listOf("a", "b", "c") if (-1 !in 0..list.lastIndex) < println("-1 не принадлежит диапазону") >if (list.size !in list.indices)
Перебор значений в заданном интервале.
Или по арифметической прогрессии.
for (x in 1..10 step 2) < print(x) >println() for (x in 9 downTo 0 step 3)
Коллекции
Проверка, содержит ли коллекция данный объект, с помощью оператора in .
val items = setOf("яблоко", "банан", "киви") when < "апельсин" in items ->println("сочно") "apple" in items -> println("яблоко тоже подойдет") >
Использование лямбда-выражения для фильтрации и модификации коллекции.
val fruits = listOf("банан", "авокадо", "яблоко", "киви") fruits .filter < it.startsWith("а") >.sortedBy < it >.map < it.uppercase() >.forEach
Nullable-значения и проверка на null
Ссылка должна быть явно объявлена как nullable (символ ? в конце имени), когда она может принимать значение null .
Возвращает null , если str не содержит числа.
fun parseInt(str: String): Int? < // . >
Использование функции, возвращающей null .
fun printProduct(arg1: String, arg2: String) < val x = parseInt(arg1) val y = parseInt(arg2) // Использование `x * y` приведет к ошибке, потому что они могут содержать null if (x != null && y != null) < // x и y автоматически приведены к не-nullable после проверки на null print(x * y) >else < println("'$arg1' или '$arg2' не число") >>
// . if (x == null) < print("Неверный формат числа arg1: '$arg1'") return >if (y == null) < print("Неверный формат числа arg2: '$arg2'") return >// x и y автоматически приведены к не-nullable после проверки на null print(x * y)
Проверка типа и автоматическое приведение типов
Оператор is проверяет, является ли выражение экземпляром заданного типа. Если неизменяемая локальная переменная или свойство уже проверены на определенный тип, то в дальнейшем нет необходимости явно приводить к этому типу:
fun getStringLength(obj: Any): Int? < if (obj is String) < // в этом блоке `obj` автоматически преобразован в `String` return obj.length >// `obj` имеет тип `Any` вне блока проверки типа return null >
fun getStringLength(obj: Any): Int? < if (obj !is String) return null // в этом блоке `obj` автоматически преобразован в `String` return obj.length >
fun getStringLength(obj: Any): Int? < // `obj` автоматически преобразован в `String` справа от оператора `&&` if (obj is String && obj.length >0) < return obj.length >return null >
Basic syntax
This is a collection of basic syntax elements with examples. At the end of every section, you’ll find a link to a detailed description of the related topic.
You can also learn all the Kotlin essentials with the free Kotlin Core track by JetBrains Academy.
Package definition and imports
Package specification should be at the top of the source file.
It is not required to match directories and packages: source files can be placed arbitrarily in the file system.
Program entry point
An entry point of a Kotlin application is the main function.
Another form of main accepts a variable number of String arguments.
Print to the standard output
print prints its argument to the standard output.
println prints its arguments and adds a line break, so that the next thing you print appears on the next line.
Functions
A function with two Int parameters and Int return type.
A function body can be an expression. Its return type is inferred.
A function that returns no meaningful value.
Unit return type can be omitted.
Variables
Read-only local variables are defined using the keyword val . They can be assigned a value only once.
Variables that can be reassigned use the var keyword.
You can declare variables at the top level.
Creating classes and instances
To define a class, use the class keyword.
Properties of a class can be listed in its declaration or body.
The default constructor with parameters listed in the class declaration is available automatically.
Inheritance between classes is declared by a colon ( : ). Classes are final by default; to make a class inheritable, mark it as open .
Comments
Just like most modern languages, Kotlin supports single-line (or end-of-line) and multi-line (block) comments.
Block comments in Kotlin can be nested.
See Documenting Kotlin Code for information on the documentation comment syntax.
String templates
Conditional expressions
In Kotlin, if can also be used as an expression.