Kotlin Docs
Kotlin Docs
Table of Contents
Overview 4
Kotlin/Native 8
Getting Started 18
Basic Syntax 18
Idioms 24
Coding Conventions 29
Basics 31
Basic Types 31
Packages 36
Interfaces 52
Visibility Modifiers 54
Extensions 56
Data Classes 61
Sealed Classes 63
Generics 64
Enum Classes 70
Delegation 76
Delegated Properties 77
Functions 83
Inline Functions 94
Coroutines 97
Other 102
Ranges 106
2
Type Checks and Casts: 'is' and 'as' 109
Equality 112
Exceptions 119
Annotations 121
Reflection 125
Reference 139
Grammar 143
Notation 143
Semicolons 143
Syntax 143
Compatibility 153
JavaScript 173
Example 184
Tools 185
FAQ 211
FAQ 211
3
Overview
Using Kotlin for Server-side Development
Kotlin is a great t for developing server-side applications, allowing to write concise and expressive code while maintaining full
compatibility with existing Java-based technology stacks and a smooth learning curve:
Expressiveness: Kotlin's innovative language features, such as its support for type-safe builders and delegated properties,
help build powerful and easy-to-use abstractions.
Scalability: Kotlin's support for coroutines helps build server-side applications that scale to massive numbers of clients with
modest hardware requirements.
Interoperability: Kotlin is fully compatible with all Java-based frameworks, which lets you stay on your familiar technology
stack while reaping the benets of a more modern language.
Migration: Kotlin supports gradual, step by step migration of large codebases from Java to Kotlin. You can start writing new
code in Kotlin while keeping older parts of your system in Java.
Tooling: In addition to great IDE support in general, Kotlin oers framework-specic tooling (for example, for Spring) in the
plugin for IntelliJ IDEA Ultimate.
Learning Curve: For a Java developer, getting started with Kotlin is very easy. The automated Java to Kotlin converter
included in the Kotlin plugin helps with the rst steps. Kotlin Koans oer a guide through the key features of the language
with a series of interactive exercises.
Vert.x, a framework for building reactive Web applications on the JVM, oers dedicated support for Kotlin, including full
documentation.
Ktor is a Kotlin-native Web framework built by JetBrains, making use of coroutines for high scalability and oering an easy-to-
use and idiomatic API.
kotlinx.html is a DSL that can be used to build HTML in a Web application. It serves as an alternative to traditional templating
systems such as JSP and FreeMarker.
The available options for persistence include direct JDBC access, JPA, as well as using NoSQL databases through their Java
drivers. For JPA, the kotlin-jpa compiler plugin adapts Kotlin-compiled classes to the requirements of the framework.
To deploy Kotlin applications on Heroku, you can follow the ocial Heroku tutorial.
AWS Labs provides a sample project showing the use of Kotlin for writing AWS Lambda functions.
JetBrains Account, the system responsible for the entire license sales and validation process at JetBrains, is written in 100%
Kotlin and has been running in production since 2015 with no major issues.
4
Next Steps
The Creating Web Applications with Http Servlets and Creating a RESTful Web Service with Spring Boot tutorials show you
how you can build and run very small Web applications in Kotlin.
For a more in-depth introduction to the language, check out the reference documentation on this site and Kotlin Koans.
5
Using Kotlin for Android Development
Kotlin is a great t for developing Android applications, bringing all of the advantages of a modern language to the Android
platform without introducing any new restrictions:
Compatibility: Kotlin is fully compatible with JDK 6, ensuring that Kotlin applications can run on older Android devices with
no issues. The Kotlin tooling is fully supported in Android Studio and compatible with the Android build system.
Performance: A Kotlin application runs as fast as an equivalent Java one, thanks to very similar bytecode structure. With
Kotlin's support for inline functions, code using lambdas often runs even faster than the same code written in Java.
Interoperability: Kotlin is 100% interoperable with Java, allowing to use all existing Android libraries in a Kotlin application.
This includes annotation processing, so databinding and Dagger work too.
Footprint: Kotlin has a very compact runtime library, which can be further reduced through the use of ProGuard. In a real
application, the Kotlin runtime adds only a few hundred methods and less than 100K to the size of the .apk le.
Compilation Time: Kotlin supports ecient incremental compilation, so while there's some additional overhead for clean
builds, incremental builds are usually as fast or faster than with Java.
Learning Curve: For a Java developer, getting started with Kotlin is very easy. The automated Java to Kotlin converter
included in the Kotlin plugin helps with the rst steps. Kotlin Koans oer a guide through the key features of the language
with a series of interactive exercises.
Pinterest has successfully introduced Kotlin into their application, used by 150M people every month.
Basecamp's Android app is 100% Kotlin code, and they report a huge dierence in programmer happiness and great
improvements in work quality and speed.
Keepsafe's App Lock app has also been converted to 100% Kotlin, leading to a 30% decrease in source line count and 10%
decrease in method count.
Kotlin Android Extensions is a compiler extension that allows you to get rid of findViewById() calls in your code and to
replace them with synthetic compiler-generated properties.
Anko is a library providing a set of Kotlin-friendly wrappers around the Android APIs, as well as a DSL that lets your replace
your layout .xml les with Kotlin code.
Next Steps
Download an install Android Studio 3.0, which includes Kotlin support out of the box.
Follow the Getting Started with Android and Kotlin tutorial to create your rst Kotlin application.
For a more in-depth introduction, check out the reference documentation on this site and Kotlin Koans.
Another great resource is Kotlin for Android Developers, a book that guides you step by step through the process of
creating a real Android application in Kotlin.
Check out Google's sample projects written in Kotlin.
6
Kotlin JavaScript Overview
Kotlin provides the ability to target JavaScript. It does so by transpiling Kotlin to JavaScript. The current implementation targets
ECMAScript 5.1 but there are plans to eventually target ECMAScript 2015 also.
When you choose the JavaScript target, any Kotlin code that is part of the project as well as the standard library that ships with
Kotlin is transpiled to JavaScript. However, this excludes the JDK and any JVM or Java framework or library used. Any le that is not
Kotlin will be ignored during compilation.
Interacting with DOM elements. Kotlin provides a series of statically typed interfaces to interact with the Document
Object Model, allowing creation and update of DOM elements.
Interacting with graphics such as WebGL. You can use Kotlin to create graphical elements on a web page using
WebGL.
Working with server-side technology. You can use Kotlin to interact with server-side JavaScript such as node.js
Kotlin can be used together with existing third-party libraries and frameworks, such as JQuery or ReactJS. To access third-party
frameworks with a strongly-typed API, you can convert TypeScript denitions from the Denitely Typed type denitions repository
to Kotlin using the ts2kt tool. Alternatively, you can use the dynamic type to access any framework without strong typing.
Kotlin is also compatible with CommonJS, AMD and UMD, making interaction with dierent module systems straightforward.
7
Kotlin/Native
Kotlin/Native is a technology for compiling Kotlin to native binaries that run without any VM. It comprises a LLVM-based backend
for the Kotlin compiler and a native implementation of the Kotlin runtime library. Kotlin/Native is primarily designed to allow
compilation for platforms where virtual machines are not desirable or possible (such as iOS, embedded targets), or where a
developer needs to produce a reasonably-sized self-contained program that does not require an additional runtime.
Kotlin/Native fully supports interoperability with native code. For platform libraries, the corresponding interop libraries are available
out of the box. For other libraries, we provide a tool to generate an interop library from a C header le, with full support for all C
language features. On macOS and iOS, interoperability with Objective/C code is also supported.
Kotlin/Native is currently in development; preview releases are available for you to try. IDE support for Kotlin/Native is available as
plugins for CLion.
Target Platforms
Sample Projects
The KotlinConf app is an iOS app with a UIKit-based UI, showcasing the Objective/C interop facilities of Kotlin/Native.
8
What's New in Kotlin 1.1
Table of Contents
Coroutines
Other language features
Standard library
JVM backend
JavaScript backend
JavaScript
Starting with Kotlin 1.1, the JavaScript target is no longer considered experimental. All language features are supported, and
there are many new tools for integration with the front-end development environment. See below for a more detailed list of
changes.
Coroutines (experimental)
The key new feature in Kotlin 1.1 is coroutines , bringing the support of async / await , yield and similar programming
patterns. The key feature of Kotlin's design is that the implementation of coroutine execution is part of the libraries, not the
language, so you aren't bound to any specic programming paradigm or concurrency library.
A coroutine is eectively a light-weight thread that can be suspended and resumed later. Coroutines are supported through
suspending functions : a call to such a function can potentially suspend a coroutine, and to start a new coroutine we usually use
an anonymous suspending functions (i.e. suspending lambdas).
Here, async { ... } starts a coroutine and, when we use await() , the execution of the coroutine is suspended while the
operation being awaited is executed, and is resumed (possibly on a dierent thread) when the operation being awaited
completes.
The standard library uses coroutines to support lazily generated sequences with yield and yieldAll functions. In such a
sequence, the block of code that returns sequence elements is suspended after each element has been retrieved, and
resumed when the next element is requested. Here's an example:
9
val seq = buildSequence {
for (i in 1..5) {
// yield a square of i
yield(i * i)
}
// yield a range
yieldAll(26..28)
}
Run the code above to see the result. Feel free to edit it and run again!
For more information, please refer to the coroutine documentation and tutorial.
Note that coroutines are currently considered an experimental feature, meaning that the Kotlin team is not committing to
supporting the backwards compatibility of this feature after the nal 1.1 release.
Type aliases
A type alias allows you to dene an alternative name for an existing type. This is most useful for generic types such as
collections, as well as for function types. Here is an example:
// Note that the type names (initial and the type alias) are interchangeable:
fun checkLaLaLandIsTheBestMovie(oscarWinners: Map<String, String>) =
oscarWinners["Best picture"] == "La La Land"
You can now use the :: operator to get a member reference pointing to a method or property of a specic object instance.
Previously this could only be expressed with a lambda. Here's an example:
Kotlin 1.1 removes some of the restrictions on sealed and data classes that were present in Kotlin 1.0. Now you can dene
subclasses of a top-level sealed class on the top level in the same le, and not just as nested classes of the sealed class. Data
classes can now extend other classes. This can be used to dene a hierarchy of expression classes nicely and cleanly:
10
sealed class Expr
Read the documentation or sealed class and data class KEEPs for more detail.
Destructuring in lambdas
You can now use the destructuring declaration syntax to unpack the arguments passed to a lambda. Here's an example:
For a lambda with multiple parameters, you can use the _ character to replace the names of the parameters you don't use:
Just as in Java 8, Kotlin now allows to use underscores in numeric literals to separate groups of digits:
For properties with the getter dened as an expression body, the property type can now be omitted:
11
Inline property accessors
You can now mark property accessors with the inline modier if the properties don't have a backing eld. Such accessors are
compiled in the same way as inline functions.
You can also mark the entire property as inline - then the modier is applied to both accessors.
You can now use the delegated property syntax with local variables. One possible use is dening a lazily evaluated local variable:
For delegated properties, it is now possible to intercept delegate to property binding using the provideDelegate operator. For
example, if we want to check the property name before binding, we can write something like this:
class MyUI {
val image by bindResource(ResourceID.image_id)
val text by bindResource(ResourceID.text_id)
}
The provideDelegate method will be called for each property during the creation of a MyUI instance, and it can perform the
necessary validation right away.
12
enum class RGB { RED, GREEN, BLUE }
The @DslMarker annotation allows to restrict the use of receivers from outer scopes in a DSL context. Consider the canonical
HTML builder example:
table {
tr {
td { +"Text" }
}
}
In Kotlin 1.0, code in the lambda passed to td has access to three implicit receivers: the one passed to table , to tr and to
td . This allows you to call methods that make no sense in the context - for example to call tr inside td and thus to put a
<tr> tag in a <td> .
In Kotlin 1.1, you can restrict that, so that only methods dened on the implicit receiver of td will be available inside the lambda
passed to td . You do that by dening your annotation marked with the @DslMarker meta-annotation and applying it to the
base class of the tag classes.
rem operator
The mod operator is now deprecated, and rem is used instead. See this issue for motivation.
Standard library
There is a bunch of new extensions on the String class to convert it to a number without throwing an exception on invalid
number: String.toIntOrNull(): Int? , String.toDoubleOrNull(): Double? etc.
Also integer conversion functions, like Int.toString() , String.toInt() , String.toIntOrNull() , each got an overload with
radix parameter, which allows to specify the base of conversion (2 to 36).
onEach()
onEach is a small, but useful extension function for collections and sequences, which allows to perform some action, possibly
with side-eects, on each element of the collection/sequence in a chain of operations. On iterables it behaves like forEach but
also returns the iterable instance further. And on sequences it returns a wrapping sequence, which applies the given action
lazily as the elements are being iterated.
inputDir.walk()
.filter { it.isFile && it.name.endsWith(".txt") }
.onEach { println("Moving $it to $outputDir") }
.forEach { moveFile(it, File(outputDir, it.toRelativeString(inputDir))) }
13
also is like apply : it takes the receiver, does some action on it, and returns that receiver. The dierence is that in the block
inside apply the receiver is available as this , while in the block inside also it's available as it (and you can give it another
name if you want). This comes handy when you do not want to shadow this from the outer scope:
takeIf is like filter for a single value. It checks whether the receiver meets the predicate, and returns the receiver, if it does
or null if it doesn't. Combined with an elvis-operator and early returns it allows to write constructs like:
takeUnless is the same as takeIf , but it takes the inverted predicate. It returns the receiver when it doesn't meet the
predicate and null otherwise. So one of the examples above could be rewritten with takeUnless as following:
It is also convenient to use when you have a callable reference instead of the lambda:
groupingBy()
This API can be used to group a collection by key and fold each group simultaneously. For example, it can be used to count the
number of words starting with each letter:
Map.minus(key)
The operator plus provides a way to add key-value pair(s) to a read-only map producing a new map, however there was not a
simple way to do the opposite: to remove a key from the map you have to resort to less straightforward ways to like
Map.filter() or Map.filterKeys() . Now the operator minus lls this gap. There are 4 overloads available: for removing a
single key, a collection of keys, a sequence of keys and an array of keys.
These functions can be used to nd the lowest and greatest of two or three given values, where values are primitive numbers
or Comparable objects. There is also an overload of each function that take an additional Comparator instance, if you want to
compare objects that are not comparable themselves.
14
val list1 = listOf("a", "b")
val list2 = listOf("x", "y", "z")
val minSize = minOf(list1.size, list2.size)
val longestList = maxOf(list1, list2, compareBy { it.size })
Similar to the Array constructor, there are now functions that create List and MutableList instances and initialize each
element by calling a lambda:
Map.getValue()
This extension on Map returns an existing value corresponding to the given key or throws an exception, mentioning which key
was not found. If the map was produced with withDefault , this function will return the default value instead of throwing an
exception.
Abstract collections
These abstract classes can be used as base classes when implementing Kotlin collection classes. For implementing read-only
collections there are AbstractCollection , AbstractList , AbstractSet and AbstractMap , and for mutable collections there
are AbstractMutableCollection , AbstractMutableList , AbstractMutableSet and AbstractMutableMap . On JVM these
abstract mutable collections inherit most of their functionality from JDK's abstract collections.
The standard library now provides a set of functions for element-by-element operations on arrays: comparison ( contentEquals
and contentDeepEquals ), hash code calculation ( contentHashCode and contentDeepHashCode ), and conversion to a string
( contentToString and contentDeepToString ). They're supported both for the JVM (where they act as aliases for the
corresponding functions in java.util.Arrays ) and for JS (where the implementation is provided in the Kotlin standard library).
JVM Backend
Kotlin has now the option of generating Java 8 bytecode ( -jvm-target 1.8 command line option or the corresponding options
in Ant/Maven/Gradle). For now this doesn't change the semantics of the bytecode (in particular, default methods in interfaces
and lambdas are generated exactly as in Kotlin 1.0), but we plan to make further use of this later.
15
There are now separate versions of the standard library supporting the new JDK APIs added in Java 7 and 8. If you need access
to the new APIs, use kotlin-stdlib-jre7 and kotlin-stdlib-jre8 maven artifacts instead of the standard kotlin-stdlib .
These artifacts are tiny extensions on top of kotlin-stdlib and they bring it to your project as a transitive dependency.
Kotlin now supports storing parameter names in the bytecode. This can be enabled using the -java-parameters command
line option.
Constant inlining
The compiler now inlines values of const val properties into the locations where they are used.
The box classes used for capturing mutable closure variables in lambdas no longer have volatile elds. This change improves
performance, but can lead to new race conditions in some rare usage scenarios. If you're aected by this, you need to provide
your own synchronization for accessing the variables.
javax.script support
Kotlin now integrates with the javax.script API (JSR-223). The API allows to evaluate snippets of code at runtime:
kotlin.re ect.full
To prepare for Java 9 support, the extension functions and properties in the kotlin-reflect.jar library have been moved to
the package kotlin.reflect.full . The names in the old package ( kotlin.reflect ) are deprecated and will be removed in
Kotlin 1.2. Note that the core reection interfaces (such as KClass ) are part of the Kotlin standard library, not kotlin-reflect ,
and are not aected by the move.
JavaScript Backend
A much larger part of the Kotlin standard library can now be used from code compiled to JavaScript. In particular, key classes
such as collections ( ArrayList , HashMap etc.), exceptions ( IllegalArgumentException etc.) and a few others
( StringBuilder , Comparator ) are now dened under the kotlin package. On the JVM, the names are type aliases for the
corresponding JDK classes, and on the JS, the classes are implemented in the Kotlin standard library.
JavaScript backend now generates more statically checkable code, which is friendlier to JS code processing tools, like miniers,
optimisers, linters, etc.
If you need to access a class implemented in JavaScript from Kotlin in a typesafe way, you can write a Kotlin declaration using the
external modier. (In Kotlin 1.0, the @native annotation was used instead.) Unlike the JVM target, the JS one permits to use
external modier with classes and properties. For example, here's how you can declare the DOM Node class:
16
external class Node {
val firstChild: Node
// etc
}
You can now describe declarations which should be imported from JavaScript modules more precisely. If you add the
@JsModule("<module-name>") annotation on an external declaration it will be properly imported to a module system (either
CommonJS or AMD) during the compilation. For example, with CommonJS the declaration will be imported via require(...)
function. Additionally, if you want to import a declaration either as a module or as a global JavaScript object, you can use the
@JsNonModule annotation.
For example, here's how you can import JQuery into a Kotlin module:
@JsModule("jquery")
@JsNonModule
@JsName("$")
external fun jquery(selector: String): JQuery
In this case, JQuery will be imported as a module named jquery . Alternatively, it can be used as a $-object, depending on what
module system Kotlin compiler is congured to use.
17
Getting Started
Basic Syntax
De ning packages
Package specication should be at the top of the source le:
package my.demo
import java.util.*
// ...
It is not required to match directories and packages: source les can be placed arbitrarily in the le system.
See Packages.
De ning functions
Function having two Int parameters with Int return type:
See Functions.
De ning variables
Assign-once (read-only) local variable:
18
val a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 3 // deferred assignment
Mutable variable:
Top-level variables:
val PI = 3.14
var x = 0
fun incrementX() {
x += 1
}
Comments
Just like Java and JavaScript, Kotlin supports end-of-line and block comments.
See Documenting Kotlin Code for information on the documentation comment syntax.
var a = 1
// simple name in template:
val s1 = "a is $a"
a = 2
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"
Using if as an expression:
19
See if-expressions.
or
// ...
if (x == null) {
println("Wrong number format in arg1: '$arg1'")
return
}
if (y == null) {
println("Wrong number format in arg2: '$arg2'")
return
}
See Null-safety.
or
20
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
or even
return null
}
or
21
Using ranges
Check if a number is within a range using in operator:
val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range")
}
for (x in 1..5) {
print(x)
}
or over a progression:
See Ranges.
Using collections
Iterating over a collection:
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }
22
See Higher-order functions and Lambdas.
23
Idioms
A collection of random and frequently used idioms in Kotlin. If you have a favorite idiom, contribute it by sending a pull request.
hashCode()
toString()
copy()
component1() , component2() , , for all properties (see Data classes)
Filtering a list
String Interpolation
println("Name $name")
Instance Checks
when (x) {
is Foo -> ...
is Bar -> ...
else -> ...
}
Using ranges
24
for (i in 1..100) { ... } // closed range: includes 100
for (i in 1 until 100) { ... } // half-open range: does not include 100
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }
Read-only list
Read-only map
Accessing a map
println(map["key"])
map["key"] = value
Lazy property
Extension Functions
Creating a singleton
object Resource {
val name = "Name"
}
println(files?.size)
println(files?.size ?: "empty")
25
val values = ...
val email = values["email"] ?: throw IllegalStateException("Email is missing!")
value?.let {
... // execute this block if not null
}
'try/catch' expression
fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}
'if' expression
26
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
Single-expression functions
fun theAnswer() = 42
This is equivalent to
This can be eectively combined with other idioms, leading to shorter code. E.g. with the when-expression:
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
Convenient form for a generic function that requires the generic type information
27
Consuming a nullable Boolean
28
Coding Conventions
This page contains the current coding style for the Kotlin language.
Naming Style
If in doubt, default to the Java Coding Conventions such as:
Colon
There is a space before colon where colon separates type and supertype and there's no space where colon separates instance
and type:
Lambdas
In lambda expressions, spaces should be used around the curly braces, as well as around the arrow which separates the
parameters from the body. Whenever possible, a lambda should be passed outside of parentheses.
In lambdas which are short and not nested, it's recommended to use the it convention instead of declaring the parameter
explicitly. In nested lambdas with parameters, parameters should be always declared explicitly.
Classes with longer headers should be formatted so that each primary constructor argument is in a separate line with
indentation. Also, the closing parenthesis should be on a new line. If we use inheritance, then the superclass constructor call or
list of implemented interfaces should be located on the same line as the parenthesis:
class Person(
id: Int,
name: String,
surname: String
) : Human(id, name) {
// ...
}
For multiple interfaces, the superclass constructor call should be located rst and then each interface should be located in a
dierent line:
29
class Person(
id: Int,
name: String,
surname: String
) : Human(id, name),
KotlinMaker {
// ...
}
Constructor parameters can use either the regular indent or the continuation indent (double the regular indent).
Unit
If a function returns Unit, the return type should be omitted:
Functions vs Properties
In some cases functions with no arguments might be interchangeable with read-only properties. Although the semantics are
similar, there are some stylistic conventions on when to prefer one to another.
30
Basics
Basic Types
In Kotlin, everything is an object in the sense that we can call member functions and properties on any variable. Some of the
types can have a special internal representation - for example, numbers, characters and booleans can be represented as
primitive values at runtime - but to the user they look like ordinary classes. In this section we describe the basic types used in
Kotlin: numbers, characters, booleans, arrays, and strings.
Numbers
Kotlin handles numbers in a way close to Java, but not exactly the same. For example, there are no implicit widening conversions
for numbers, and literals are slightly dierent in some cases.
Kotlin provides the following built-in types representing numbers (this is close to Java):
Literal Constants
There are the following kinds of literal constants for integral values:
Decimals: 123
Longs are tagged by a capital L : 123L
Hexadecimals: 0x0F
Binaries: 0b00001011
31
Representation
On the Java platform, numbers are physically stored as JVM primitive types, unless we need a nullable number reference (e.g.
Int? ) or generics are involved. In the latter cases numbers are boxed.
Explicit Conversions
Due to dierent representations, smaller types are not subtypes of bigger ones. If they were, we would have troubles of the
following sort:
So not only identity, but even equality would have been lost silently all over the place.
As a consequence, smaller types are NOT implicitly converted to bigger types. This means that we cannot assign a value of type
Byte to an Int variable without an explicit conversion
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
Absence of implicit conversions is rarely noticeable because the type is inferred from the context, and arithmetical operations
are overloaded for appropriate conversions, for example
32
Operations
Kotlin supports the standard set of arithmetical operations over numbers, which are declared as members of appropriate
classes (but the compiler optimizes the calls down to the corresponding instructions). See Operator overloading.
As of bitwise operations, there're no special characters for them, but just named functions that can be called in inx form, for
example:
Here is the complete list of bitwise operations (available for Int and Long only):
When the operands a and b are statically known to be Float or Double or their nullable counterparts (the type is declared or
inferred or is a result of a smart cast), the operations on the numbers and the range that they form follow the IEEE 754 Standard
for Floating-Point Arithmetic.
However, to support generic use cases and provide total ordering, when the operands are not statically typed as oating point
numbers (e.g. Any , Comparable<...> , a type parameter), the operations use the equals and compareTo implementations for
Float and Double , which disagree with the standard, so that:
Characters
Characters are represented by the type Char . They can not be treated directly as numbers
Character literals go in single quotes: '1' . Special characters can be escaped using a backslash. The following escape
sequences are supported: \t , \b , \n , \r , \' , \" , \\ and \$ . To encode any other character, use the Unicode escape
sequence syntax: '\uFF00' .
33
fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // Explicit conversions to numbers
}
Like numbers, characters are boxed when a nullable reference is needed. Identity is not preserved by the boxing operation.
Booleans
The type Boolean represents booleans, and has two values: true and false.
|| lazy disjunction
&& lazy conjunction
! - negation
Arrays
Arrays in Kotlin are represented by the Array class, that has get and set functions (that turn into [] by operator overloading
conventions), and size property, along with a few other useful member functions:
To create an array, we can use a library function arrayOf() and pass the item values to it, so that arrayOf(1, 2, 3) creates
an array [1, 2, 3]. Alternatively, the arrayOfNulls() library function can be used to create an array of a given size lled with null
elements.
Another option is to use a factory function that takes the array size and the function that can return the initial value of each array
element given its index:
As we said above, the [] operation stands for calls to member functions get() and set() .
Note: unlike Java, arrays in Kotlin are invariant. This means that Kotlin does not let us assign an Array<String> to an
Array<Any> , which prevents a possible runtime failure (but you can use Array<out Any> , see Type Projections).
Kotlin also has specialized classes to represent arrays of primitive types without boxing overhead: ByteArray , ShortArray ,
IntArray and so on. These classes have no inheritance relation to the Array class, but they have the same set of methods
and properties. Each of them also has a corresponding factory function:
Strings
Strings are represented by the type String . Strings are immutable. Elements of a string are characters that can be accessed
by the indexing operation: s[i] . A string can be iterated over with a for-loop:
34
for (c in str) {
println(c)
}
String Literals
Kotlin has two types of string literals: escaped strings that may have escaped characters in them and raw strings that can
contain newlines and arbitrary text. An escaped string is very much like a Java string:
Escaping is done in the conventional way, with a backslash. See Characters above for the list of supported escape sequences.
A raw string is delimited by a triple quote ( """ ), contains no escaping and can contain newlines and any other characters:
By default | is used as margin prex, but you can choose another character and pass it as a parameter, like trimMargin(">") .
String Templates
Strings may contain template expressions, i.e. pieces of code that are evaluated and whose results are concatenated into the
string. A template expression starts with a dollar sign ($) and consists of either a simple name:
val i = 10
val s = "i = $i" // evaluates to "i = 10"
val s = "abc"
val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3"
Templates are supported both inside raw strings and inside escaped strings. If you need to represent a literal $ character in a
raw string (which doesn't support backslash escaping), you can use the following syntax:
35
Packages
A source le may start with a package declaration:
package foo.bar
fun baz() {}
class Goo {}
// ...
All the contents (such as classes and functions) of the source le are contained by the package declared. So, in the example
above, the full name of baz() is foo.bar.baz , and the full name of Goo is foo.bar.Goo .
If the package is not specied, the contents of such a le belong to "default" package that has no name.
Default Imports
A number of packages are imported into every Kotlin le by default:
kotlin.*
kotlin.annotation.*
kotlin.collections.*
kotlin.comparisons.* (since 1.1)
kotlin.io.*
kotlin.ranges.*
kotlin.sequences.*
kotlin.text.*
JVM:
java.lang.*
kotlin.jvm.*
JS:
kotlin.js.*
Imports
Apart from the default imports, each le may contain its own import directives. Syntax for imports is described in the grammar.
If there is a name clash, we can disambiguate by using as keyword to locally rename the clashing entity:
The import keyword is not restricted to importing classes; you can also use it to import other declarations:
36
functions and properties declared in object declarations;
enum constants.
Unlike Java, Kotlin does not have a separate "import static" syntax; all of these declarations are imported using the regular
import keyword.
37
Control Flow: if, when, for, while
If Expression
In Kotlin, if is an expression, i.e. it returns a value. Therefore there is no ternary operator (condition ? then : else), because
ordinary if works ne in this role.
// Traditional usage
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// As expression
val max = if (a > b) a else b
if branches can be blocks, and the last expression is the value of a block:
If you're using if as an expression rather than a statement (for example, returning its value or assigning it to a variable), the
expression is required to have an else branch.
When Expression
when replaces the switch operator of C-like languages. In the simplest form it looks like this
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}
when matches its argument against all branches sequentially until some branch condition is satised. when can be used either as
an expression or as a statement. If it is used as an expression, the value of the satised branch becomes the value of the overall
expression. If it is used as a statement, the values of individual branches are ignored. (Just like with if, each branch can be a
block, and its value is the value of the last expression in the block.)
The else branch is evaluated if none of the other branch conditions are satised. If when is used as an expression, the else
branch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions.
If many cases should be handled in the same way, the branch conditions may be combined with a comma:
38
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
Another possibility is to check that a value is or !is of a particular type. Note that, due to smart casts, you can access the
methods and properties of the type without any extra checks.
when can also be used as a replacement for an if-else if chain. If no argument is supplied, the branch conditions are simply
boolean expressions, and a branch is executed when its condition is true:
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
For Loops
for loop iterates through anything that provides an iterator. This is equivalent to the foreach loop in languages like C#. The
syntax is as follows:
As mentioned before, for iterates through anything that provides an iterator, i.e.
39
All of these three functions need to be marked as operator .
A for loop over an array is compiled to an index-based loop that does not create an iterator object.
If you want to iterate through an array or a list with an index, you can do it this way:
for (i in array.indices) {
print(array[i])
}
Note that this "iteration through a range" is compiled down to optimal implementation with no extra objects created.
While Loops
while and do..while work as usual
while (x > 0) {
x--
}
do {
val y = retrieveData()
} while (y != null) // y is visible here!
40
Returns and Jumps
Kotlin has three structural jump expressions:
return. By default returns from the nearest enclosing function or anonymous function.
break. Terminates the nearest enclosing loop.
A break qualied with a label jumps to the execution point right after the loop marked with that label. A continue proceeds to
the next iteration of that loop.
Return at Labels
With function literals, local functions and object expression, functions can be nested in Kotlin. Qualied returns allow us to
return from an outer function. The most important use case is returning from a lambda expression. Recall that when we write
this:
fun foo() {
ints.forEach {
if (it == 0) return // nonlocal return from inside lambda directly to the caller of foo()
print(it)
}
}
The return-expression returns from the nearest enclosing function, i.e. foo . (Note that such non-local returns are supported
only for lambda expressions passed to inline functions.) If we need to return from a lambda expression, we have to label it and
qualify the return:
fun foo() {
ints.forEach lit@ {
if (it == 0) return@lit
print(it)
}
}
Now, it returns only from the lambda expression. Oftentimes it is more convenient to use implicits labels: such a label has the
same name as the function to which the lambda is passed.
41
fun foo() {
ints.forEach {
if (it == 0) return@forEach
print(it)
}
}
Alternatively, we can replace the lambda expression with an anonymous function. A return statement in an anonymous function
will return from the anonymous function itself.
fun foo() {
ints.forEach(fun(value: Int) {
if (value == 0) return // local return to the caller of the anonymous fun, i.e. the forEach loop
print(value)
})
}
When returning a value, the parser gives preference to the qualied return, i.e.
return@a 1
means "return 1 at label @a " and not "return a labeled expression (@a 1) ".
42
Classes and Objects
Classes and Inheritance
Classes
Classes in Kotlin are declared using the keyword class:
class Invoice {
}
The class declaration consists of the class name, the class header (specifying its type parameters, the primary constructor etc.)
and the class body, surrounded by curly braces. Both the header and the body are optional; if the class has no body, curly
braces can be omitted.
class Empty
Constructors
A class in Kotlin can have a primary constructor and one or more secondary constructors. The primary constructor is part
of the class header: it goes after the class name (and optional type parameters).
If the primary constructor does not have any annotations or visibility modiers, the constructor keyword can be omitted:
The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks, which are prexed with
the init keyword:
Note that parameters of the primary constructor can be used in the initializer blocks. They can also be used in property
initializers declared in the class body:
In fact, for declaring properties and initializing them from the primary constructor, Kotlin has a concise syntax:
43
class Person(val firstName: String, val lastName: String, var age: Int) {
// ...
}
Much the same way as regular properties, the properties declared in the primary constructor can be mutable (var) or read-only
(val).
If the constructor has annotations or visibility modiers, the constructor keyword is required, and the modiers go before it:
Secondary Constructors
The class can also declare secondary constructors, which are prexed with constructor:
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly
or indirectly through another secondary constructor(s). Delegation to another constructor of the same class is done using the
this keyword:
If a non-abstract class does not declare any constructors (primary or secondary), it will have a generated primary constructor
with no arguments. The visibility of the constructor will be public. If you do not want your class to have a public constructor, you
need to declare an empty primary constructor with non-default visibility:
NOTE: On the JVM, if all of the parameters of the primary constructor have default values, the compiler will generate an
additional parameterless constructor which will use the default values. This makes it easier to use Kotlin with libraries such
as Jackson or JPA that create class instances through parameterless constructors.
Creating instances of nested, inner and anonymous inner classes is described in Nested classes.
44
Class Members
Inheritance
All classes in Kotlin have a common superclass Any , that is a default super for a class with no supertypes declared:
Any is not java.lang.Object ; in particular, it does not have any members other than equals() , hashCode() and
toString() . Please consult the Java interoperability section for more details.
To declare an explicit supertype, we place the type after a colon in the class header:
If the class has a primary constructor, the base type can (and must) be initialized right there, using the parameters of the primary
constructor.
If the class has no primary constructor, then each secondary constructor has to initialize the base type using the super
keyword, or to delegate to another constructor which does that. Note that in this case dierent secondary constructors can call
dierent constructors of the base type:
The open annotation on a class is the opposite of Java's final: it allows others to inherit from this class. By default, all classes in
Kotlin are nal, which corresponds to Eective Java, Item 17: Design and document for inheritance or else prohibit it.
Overriding Methods
As we mentioned before, we stick to making things explicit in Kotlin. And unlike Java, Kotlin requires explicit annotations for
overridable members (we call them open) and for overrides:
The override annotation is required for Derived.v() . If it were missing, the compiler would complain. If there is no open
annotation on a function, like Base.nv() , declaring a method with the same signature in a subclass is illegal, either with
override or without it. In a nal class (e.g. a class with no open annotation), open members are prohibited.
A member marked override is itself open, i.e. it may be overridden in subclasses. If you want to prohibit re-overriding, use
final:
45
open class AnotherDerived() : Base() {
final override fun v() {}
}
Overriding Properties
Overriding properties works in a similar way to overriding methods; properties declared on a superclass that are then redeclared
on a derived class must be prefaced with override, and they must have a compatible type. Each declared property can be
overridden by a property with an initializer or by a property with a getter method.
You can also override a val property with a var property, but not vice versa. This is allowed because a val property
essentially declares a getter method, and overriding it as a var additionally declares a setter method in the derived class.
Note that you can use the override keyword as part of the property declaration in a primary constructor.
interface Foo {
val count: Int
}
Code in a derived class can call its superclass functions and property accessors implementations using the super keyword:
Inside an inner class, accessing the superclass of the outer class is done with the super keyword qualied with the outer class
name: super@Outer :
46
class Bar : Foo() {
override fun f() { /* ... */ }
override val x: Int get() = 0
Overriding Rules
In Kotlin, implementation inheritance is regulated by the following rule: if a class inherits many implementations of the same
member from its immediate superclasses, it must override this member and provide its own implementation (perhaps, using
one of the inherited ones). To denote the supertype from which the inherited implementation is taken, we use super qualied
by the supertype name in angle brackets, e.g. super<Base> :
open class A {
open fun f() { print("A") }
fun a() { print("a") }
}
interface B {
fun f() { print("B") } // interface members are 'open' by default
fun b() { print("b") }
}
It's ne to inherit from both A and B , and we have no problems with a() and b() since C inherits only one implementation
of each of these functions. But for f() we have two implementations inherited by C , and thus we have to override f() in C
and provide our own implementation that eliminates the ambiguity.
Abstract Classes
A class and some of its members may be declared abstract. An abstract member does not have an implementation in its class.
Note that we do not need to annotate an abstract class or function with open it goes without saying.
Companion Objects
In Kotlin, unlike Java or C#, classes do not have static methods. In most cases, it's recommended to simply use package-level
functions instead.
47
If you need to write a function that can be called without having a class instance but needs access to the internals of a class (for
example, a factory method), you can write it as a member of an object declaration inside that class.
Even more specically, if you declare a companion object inside your class, you'll be able to call its members with the same
syntax as calling static methods in Java/C#, using only the class name as a qualier.
48
Properties and Fields
Declaring Properties
Classes in Kotlin can have properties. These can be declared as mutable, using the var keyword or read-only using the val
keyword.
class Address {
var name: String = ...
var street: String = ...
var city: String = ...
var state: String? = ...
var zip: String = ...
}
The initializer, getter and setter are optional. Property type is optional if it can be inferred from the initializer (or from the getter
return type, as shown below).
Examples:
var allByDefault: Int? // error: explicit initializer required, default getter and setter implied
var initialized = 1 // has type Int, default getter and setter
The full syntax of a read-only property declaration diers from a mutable one in two ways: it starts with val instead of var and
does not allow a setter:
val simple: Int? // has type Int, default getter, must be initialized in constructor
val inferredType = 1 // has type Int and a default getter
We can write custom accessors, very much like ordinary functions, right inside a property declaration. Here's an example of a
custom getter:
49
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}
By convention, the name of the setter parameter is value , but you can choose a dierent name if you prefer.
Since Kotlin 1.1, you can omit the property type if it can be inferred from the getter:
If you need to change the visibility of an accessor or to annotate it, but don't need to change the default implementation, you
can dene the accessor without dening its body:
Backing Fields
Classes in Kotlin cannot have elds. However, sometimes it is necessary to have a backing eld when using custom accessors.
For these purposes, Kotlin provides an automatic backing eld which can be accessed using the field identier:
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0) field = value
}
The field identier can only be used in the accessors of the property.
A backing eld will be generated for a property if it uses the default implementation of at least one of the accessors, or if a
custom accessor references it through the field identier.
Backing Properties
If you want to do something that does not t into this "implicit backing eld" scheme, you can always fall back to having a
backing property:
In all respects, this is just the same as in Java since access to private properties with default getters and setters is optimized so
that no function call overhead is introduced.
Compile-Time Constants
50
Properties the value of which is known at compile time can be marked as compile time constants using the const modier.
Such properties need to full the following requirements:
No custom getter
Late-Initialized Properties
Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not
convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In
this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the
property inside the body of a class.
To handle this case, you can mark the property with the lateinit modier:
The modier can only be used on var properties declared inside the body of a class (not in the primary constructor), and only
when the property does not have a custom getter or setter. The type of the property must be non-null, and it must not be a
primitive type.
Accessing a lateinit property before it has been initialized throws a special exception that clearly identies the property
being accessed and the fact that it hasn't been initialized.
Overriding Properties
See Overriding Properties
Delegated Properties
The most common kind of properties simply reads from (and maybe writes to) a backing eld. On the other hand, with custom
getters and setters one can implement any behaviour of a property. Somewhere in between, there are certain common patterns
of how a property may work. A few examples: lazy values, reading from a map by a given key, accessing a database, notifying
listener on access, etc.
51
Interfaces
Interfaces in Kotlin are very similar to Java 8. They can contain declarations of abstract methods, as well as method
implementations. What makes them dierent from abstract classes is that interfaces cannot store state. They can have
properties but these need to be abstract or to provide accessor implementations.
interface MyInterface {
fun bar()
fun foo() {
// optional body
}
}
Implementing Interfaces
A class or object can implement one or more interfaces
Properties in Interfaces
You can declare properties in interfaces. A property declared in an interface can either be abstract, or it can provide
implementations for accessors. Properties declared in interfaces can't have backing elds, and therefore accessors declared in
interfaces can't reference them.
interface MyInterface {
val prop: Int // abstract
fun foo() {
print(prop)
}
}
52
interface A {
fun foo() { print("A") }
fun bar()
}
interface B {
fun foo() { print("B") }
fun bar() { print("bar") }
}
class C : A {
override fun bar() { print("bar") }
}
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
Interfaces A and B both declare functions foo() and bar(). Both of them implement foo(), but only B implements bar() (bar() is not
marked abstract in A, because this is the default for interfaces, if the function has no body). Now, if we derive a concrete class C
from A, we, obviously, have to override bar() and provide an implementation.
However, if we derive D from A and B , we need to implement all the methods which we have inherited from multiple interfaces,
and to specify how exactly D should implement them. This rule applies both to methods for which we've inherited a single
implementation (bar()) and multiple implementations (foo()).
53
Visibility Modi ers
Classes, objects, interfaces, constructors, functions, properties and their setters can have visibility modiers . (Getters always
have the same visibility as the property.) There are four visibility modiers in Kotlin: private , protected , internal and
public . The default visibility, used if there is no explicit modier, is public .
Packages
Functions, properties and classes, objects and interfaces can be declared on the "top-level", i.e. directly inside a package:
fun baz() {}
class Bar {}
If you do not specify any visibility modier, public is used by default, which means that your declarations will be visible
everywhere;
If you mark a declaration private , it will only be visible inside the le containing the declaration;
If you mark it internal , it is visible everywhere in the same module;
protected is not available for top-level declarations.
Note: to use a visible top-level declaration from another package, you should still import it.
Examples:
private means visible inside this class only (including all its members);
protected same as private + visible in subclasses too;
internal any client inside this module who sees the declaring class sees its internal members;
public any client who sees the declaring class sees its public members.
NOTE for Java users: outer class does not see private members of its inner classes in Kotlin.
If you override a protected member and do not specify the visibility explicitly, the overriding member will also have protected
visibility.
Examples:
54
open class Outer {
private val a = 1
protected open val b = 2
internal val c = 3
val d = 4 // public by default
Constructors
To specify a visibility of the primary constructor of a class, use the following syntax (note that you need to add an explicit
constructor keyword):
Here the constructor is private. By default, all constructors are public , which eectively amounts to them being visible
everywhere where the class is visible (i.e. a constructor of an internal class is only visible within the same module).
Local declarations
Local variables, functions and classes can not have visibility modiers.
Modules
The internal visibility modier means that the member is visible within the same module. More specically, a module is a set
of Kotlin les compiled together:
55
Extensions
Kotlin, similar to C# and Gosu, provides the ability to extend a class with new functionality without having to inherit from the class
or use any type of design pattern such as Decorator. This is done via special declarations called extensions . Kotlin supports
extension functions and extension properties .
Extension Functions
To declare an extension function, we need to prex its name with a receiver type , i.e. the type being extended. The following
adds a swap function to MutableList<Int> :
The this keyword inside an extension function corresponds to the receiver object (the one that is passed before the dot). Now,
we can call such a function on any MutableList<Int> :
val l = mutableListOf(1, 2, 3)
l.swap(0, 2) // 'this' inside 'swap()' will hold the value of 'l'
Of course, this function makes sense for any MutableList<T> , and we can make it generic:
We declare the generic type parameter before the function name for it to be available in the receiver type expression. See
Generic functions.
We would like to emphasize that extension functions are dispatched statically, i.e. they are not virtual by receiver type. This
means that the extension function being called is determined by the type of the expression on which the function is invoked,
not by the type of the result of evaluating that expression at runtime. For example:
open class C
class D: C()
fun printFoo(c: C) {
println(c.foo())
}
printFoo(D())
This example will print "c", because the extension function being called depends only on the declared type of the parameter c ,
which is the C class.
56
If a class has a member function, and an extension function is dened which has the same receiver type, the same name and is
applicable to given arguments, the member always wins. For example:
class C {
fun foo() { println("member") }
}
However, it's perfectly OK for extension functions to overload member functions which have the same name but a dierent
signature:
class C {
fun foo() { println("member") }
}
Nullable Receiver
Note that extensions can be dened with a nullable receiver type. Such extensions can be called on an object variable even if its
value is null, and can check for this == null inside the body. This is what allows you to call toString() in Kotlin without checking
for null: the check happens inside the extension function.
Extension Properties
Similarly to functions, Kotlin supports extension properties:
Note that, since extensions do not actually insert members into classes, there's no ecient way for an extension property to
have a backing eld. This is why initializers are not allowed for extension properties. Their behavior can only be dened
by explicitly providing getters/setters.
Example:
val Foo.bar = 1 // error: initializers are not allowed for extension properties
57
class MyClass {
companion object { } // will be called "Companion"
}
fun MyClass.Companion.foo() {
// ...
}
Just like regular members of the companion object, they can be called using only the class name as the qualier:
MyClass.foo()
Scope of Extensions
Most of the time we dene extensions on the top level, i.e. directly under packages:
package foo.bar
To use such an extension outside its declaring package, we need to import it at the call site:
package com.example.usage
class D {
fun bar() { ... }
}
class C {
fun baz() { ... }
fun D.foo() {
bar() // calls D.bar
baz() // calls C.baz
}
fun caller(d: D) {
d.foo() // call the extension function
}
}
In case of a name conict between the members of the dispatch receiver and the extension receiver, the extension receiver
takes precedence. To refer to the member of the dispatch receiver you can use the qualied this syntax.
58
class C {
fun D.foo() {
toString() // calls D.toString()
this@C.toString() // calls C.toString()
}
Extensions declared as members can be declared as open and overridden in subclasses. This means that the dispatch of such
functions is virtual with regard to the dispatch receiver type, but static with regard to the extension receiver type.
open class D {
}
class D1 : D() {
}
open class C {
open fun D.foo() {
println("D.foo in C")
}
fun caller(d: D) {
d.foo() // call the extension function
}
}
class C1 : C() {
override fun D.foo() {
println("D.foo in C1")
}
Motivation
In Java, we are used to classes named "*Utils": FileUtils , StringUtils and so on. The famous java.util.Collections
belongs to the same breed. And the unpleasant part about these Utils-classes is that the code that uses them looks like this:
// Java
Collections.swap(list, Collections.binarySearch(list, Collections.max(otherList)),
Collections.max(list));
Those class names are always getting in the way. We can use static imports and get this:
// Java
swap(list, binarySearch(list, max(otherList)), max(list));
This is a little better, but we have no or little help from the powerful code completion of the IDE. It would be so much better if we
could say:
59
// Java
list.swap(list.binarySearch(otherList.max()), list.max());
But we don't want to implement all the possible methods inside the class List , right? This is where extensions help us.
60
Data Classes
We frequently create classes whose main purpose is to hold data. In such a class some standard functionality and utility
functions are often mechanically derivable from the data. In Kotlin, this is called a data class and is marked as data :
The compiler automatically derives the following members from all properties declared in the primary constructor:
To ensure consistency and meaningful behavior of the generated code, data classes have to full the following requirements:
Additionally, the members generation follows these rules with regard to the members inheritance:
If there are explicit implementations of equals() , hashCode() or toString() in the data class body or final
implementations in a superclass, then these functions are not generated, and the existing implementations are used;
If a supertype has the componentN() functions that are open and return compatible types, the corresponding functions are
generated for the data class and override those of the supertype. If the functions of the supertype cannot be overridden
due to incompatible signatures or being nal, an error is reported;
Providing explicit implementations for the componentN() and copy() functions is not allowed.
Since 1.1, data classes may extend other classes (see Sealed classes for examples).
On the JVM, if the generated class needs to have a parameterless constructor, default values for all properties have to be
specied (see Constructors).
Copying
It's often the case that we need to copy an object altering some of its properties, but keeping the rest unchanged. This is what
copy() function is generated for. For the User class above, its implementation would be as follows:
61
Standard Data Classes
The standard library provides Pair and Triple . In most cases, though, named data classes are a better design choice,
because they make the code more readable by providing meaningful names for properties.
62
Sealed Classes
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set,
but cannot have any other type. They are, in a sense, an extension of enum classes: the set of values for an enum type is also
restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple
instances which can contain state.
To declare a sealed class, you put the sealed modier before the name of the class. A sealed class can have subclasses, but
all of them must be declared in the same le as the sealed class itself. (Before Kotlin 1.1, the rules were even more strict:
classes had to be nested inside the declaration of the sealed class).
(The example above uses one additional new feature of Kotlin 1.1: the possibility for data classes to extend other classes,
including sealed classes.)
A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.
Sealed classes are not allowed to have non-private constructors (their constructors are private by default).
Note that classes which extend subclasses of a sealed class (indirect inheritors) can be placed anywhere, not necessarily in the
same le.
The key benet of using sealed classes comes into play when you use them in a when expression. If it's possible to verify that
the statement covers all cases, you don't need to add an else clause to the statement. However, this works only if you use
when as an expression (using the result) and not as a statement.
63
Generics
As in Java, classes in Kotlin may have type parameters:
class Box<T>(t: T) {
var value = t
}
In general, to create an instance of such a class, we need to provide the type arguments:
But if the parameters may be inferred, e.g. from the constructor arguments or by some other means, one is allowed to omit the
type arguments:
val box = Box(1) // 1 has type Int, so the compiler figures out that we are talking about Box<Int>
Variance
One of the most tricky parts of Java's type system is wildcard types (see Java Generics FAQ). And Kotlin doesn't have any. Instead,
it has two other things: declaration-site variance and type projections.
First, let's think about why Java needs those mysterious wildcards. The problem is explained in Eective Java, Item 28: Use
bounded wildcards to increase API exibility. First, generic types in Java are invariant, meaning that List<String> is not a
subtype of List<Object> . Why so? If List was not invariant, it would have been no better than Java's arrays, since the following
code would have compiled and caused an exception at runtime:
// Java
List<String> strs = new ArrayList<String>();
List<Object> objs = strs; // !!! The cause of the upcoming problem sits here. Java prohibits this!
objs.add(1); // Here we put an Integer into a list of Strings
String s = strs.get(0); // !!! ClassCastException: Cannot cast Integer to String
So, Java prohibits such things in order to guarantee run-time safety. But this has some implications. For example, consider the
addAll() method from Collection interface. What's the signature of this method? Intuitively, we'd put it this way:
// Java
interface Collection<E> ... {
void addAll(Collection<E> items);
}
But then, we would not be able to do the following simple thing (which is perfectly safe):
// Java
void copyAll(Collection<Object> to, Collection<String> from) {
to.addAll(from); // !!! Would not compile with the naive declaration of addAll:
// Collection<String> is not a subtype of Collection<Object>
}
(In Java, we learned this lesson the hard way, see Eective Java, Item 25: Prefer lists to arrays )
// Java
interface Collection<E> ... {
void addAll(Collection<? extends E> items);
}
64
The wildcard type argument ? extends E indicates that this method accepts a collection of objects of E or some subtype
of E , not just E itself. This means that we can safely read E 's from items (elements of this collection are instances of a
subclass of E), but cannot write to it since we do not know what objects comply to that unknown subtype of E . In return for
this limitation, we have the desired behaviour: Collection<String> is a subtype of Collection<? extends Object> . In "clever
words", the wildcard with an extends-bound (upper bound) makes the type covariant.
The key to understanding why this trick works is rather simple: if you can only take items from a collection, then using a
collection of String s and reading Object s from it is ne. Conversely, if you can only put items into the collection, it's OK to
take a collection of Object s and put String s into it: in Java we have List<? super String> a supertype of List<Object> .
The latter is called contravariance, and you can only call methods that take String as an argument on List<? super String>
(e.g., you can call add(String) or set(int, String) ), while if you call something that returns T in List<T> , you don't get a
String , but an Object .
Joshua Bloch calls those objects you only read from Producers, and those you only write to Consumers. He recommends:
"For maximum exibility, use wildcard types on input parameters that represent producers or consumers ", and proposes the
following mnemonic:
NOTE: if you use a producer-object, say, List<? extends Foo> , you are not allowed to call add() or set() on this object, but
this does not mean that this object is immutable: for example, nothing prevents you from calling clear() to remove all items
from the list, since clear() does not take any parameters at all. The only thing guaranteed by wildcards (or other types of
variance) is type safety. Immutability is a completely dierent story.
Declaration-site variance
Suppose we have a generic interface Source<T> that does not have any methods that take T as a parameter, only methods
that return T :
// Java
interface Source<T> {
T nextT();
}
Then, it would be perfectly safe to store a reference to an instance of Source<String> in a variable of type Source<Object>
there are no consumer-methods to call. But Java does not know this, and still prohibits it:
// Java
void demo(Source<String> strs) {
Source<Object> objects = strs; // !!! Not allowed in Java
// ...
}
To x this, we have to declare objects of type Source<? extends Object> , which is sort of meaningless, because we can call all
the same methods on such a variable as before, so there's no value added by the more complex type. But the compiler does
not know that.
In Kotlin, there is a way to explain this sort of thing to the compiler. This is called declaration-site variance: we can annotate
the type parameter T of Source to make sure that it is only returned (produced) from members of Source<T> , and never
consumed. To do this we provide the out modier:
65
The general rule is: when a type parameter T of a class C is declared out, it may occur only in out-position in the members of
C , but in return C<Base> can safely be a supertype of C<Derived> .
In "clever words" they say that the class C is covariant in the parameter T , or that T is a covariant type parameter. You can
think of C as being a producer of T 's, and NOT a consumer of T 's.
The out modier is called a variance annotation, and since it is provided at the type parameter declaration site, we talk about
declaration-site variance. This is in contrast with Java's use-site variance where wildcards in the type usages make the
types covariant.
In addition to out, Kotlin provides a complementary variance annotation: in. It makes a type parameter contravariant: it can
only be consumed and never produced. A good example of a contravariant class is Comparable :
We believe that the words in and out are self-explaining (as they were successfully used in C# for quite some time already),
thus the mnemonic mentioned above is not really needed, and one can rephrase it for a higher purpose:
Type projections
It is very convenient to declare a type parameter T as out and avoid trouble with subtyping on the use site, but some classes
can't actually be restricted to only return T 's! A good example of this is Array:
This class cannot be either co- or contravariant in T . And this imposes certain inexibilities. Consider the following function:
This function is supposed to copy items from one array to another. Let's try to apply it in practice:
Here we run into the same familiar problem: Array<T> is invariant in T , thus neither of Array<Int> and Array<Any> is a
subtype of the other. Why? Again, because copy might be doing bad things, i.e. it might attempt to write, say, a String to from ,
and if we actually passed an array of Int there, a ClassCastException would have been thrown sometime later.
Then, the only thing we want to ensure is that copy() does not do any bad things. We want to prohibit it from writing to from ,
and we can:
66
fun copy(from: Array<out Any>, to: Array<Any>) {
// ...
}
What has happened here is called type projection: we said that from is not simply an array, but a restricted (projected) one:
we can only call those methods that return the type parameter T , in this case it means that we can only call get() . This is our
approach to use-site variance, and corresponds to Java's Array<? extends Object> , but in a slightly simpler way.
Array<in String> corresponds to Java's Array<? super String> , i.e. you can pass an array of CharSequence or an array of
Object to the fill() function.
Star-projections
Sometimes you want to say that you know nothing about the type argument, but still want to use it in a safe way. The safe way
here is to dene such a projection of the generic type, that every concrete instantiation of that generic type would be a subtype
of that projection.
For Foo<out T> , where T is a covariant type parameter with the upper bound TUpper , Foo<*> is equivalent to Foo<out
TUpper> . It means that when the T is unknown you can safely read values of TUpper from Foo<*> .
For Foo<in T> , where T is a contravariant type parameter, Foo<*> is equivalent to Foo<in Nothing> . It means there is
nothing you can write to Foo<*> in a safe way when T is unknown.
For Foo<T> , where T is an invariant type parameter with the upper bound TUpper , Foo<*> is equivalent to Foo<out
TUpper> for reading values and to Foo<in Nothing> for writing values.
If a generic type has several type parameters each of them can be projected independently. For example, if the type is declared
as interface Function<in T, out U> we can imagine the following star-projections:
Note : star-projections are very much like Java's raw types, but safe.
Generic functions
Not only classes can have type parameters. Functions can, too. Type parameters are placed before the name of the function:
To call a generic function, specify the type arguments at the call site after the name of the function:
val l = singletonList<Int>(1)
Generic constraints
The set of all possible types that can be substituted for a given type parameter may be restricted by generic constraints.
67
Upper bounds
The most common type of constraint is an upper bound that corresponds to Java's extends keyword:
The type specied after a colon is the upper bound: only a subtype of Comparable<T> may be substituted for T . For
example:
The default upper bound (if none specied) is Any? . Only one upper bound can be specied inside the angle brackets. If the
same type parameter needs more than one upper bound, we need a separate where-clause:
68
Nested and Inner Classes
Classes can be nested in other classes:
class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
}
}
Inner classes
A class may be marked as inner to be able to access members of outer class. Inner classes carry a reference to an object of an
outer class:
class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar
}
}
See Qualied this expressions to learn about disambiguation of this in inner classes.
window.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
If the object is an instance of a functional Java interface (i.e. a Java interface with a single abstract method), you can create it
using a lambda expression prexed with the type of the interface:
69
Enum Classes
The most basic usage of enum classes is implementing type-safe enums:
Each enum constant is an object. Enum constants are separated with commas.
Initialization
Since each enum is an instance of the enum class, they can be initialized as:
Anonymous Classes
Enum constants can also declare their own anonymous classes:
TALKING {
override fun signal() = WAITING
};
with their corresponding methods, as well as overriding base methods. Note that if the enum class denes any members, you
need to separate the enum constant denitions from the member denitions with a semicolon, just like in Java.
The valueOf() method throws an IllegalArgumentException if the specied name does not match any of the enum
constants dened in the class.
Since Kotlin 1.1, it's possible to access the constants in an enum class in a generic way, using the enumValues<T>() and
enumValueOf<T>() functions:
70
Every enum constant has properties to obtain its name and position in the enum class declaration:
The enum constants also implement the Comparable interface, with the natural order being the order in which they are dened
in the enum class.
71
Object Expressions and Declarations
Sometimes we need to create an object of a slight modication of some class, without explicitly declaring a new subclass for it.
Java handles this case with anonymous inner classes . Kotlin slightly generalizes this concept with object expressions and object
declarations .
Object expressions
To create an object of an anonymous class that inherits from some type (or types), we write:
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
If a supertype has a constructor, appropriate constructor parameters must be passed to it. Many supertypes may be specied
as a comma-separated list after the colon:
interface B {...}
If, by any chance, we need "just an object", with no nontrivial supertypes, we can simply say:
fun foo() {
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
}
Note that anonymous objects can be used as types only in local and private declarations. If you use an anonymous object as a
return type of a public function or the type of a public property, the actual type of that function or property will be the declared
supertype of the anonymous object, or Any if you didn't declare any supertype. Members added in the anonymous object will
not be accessible.
72
class C {
// Private function, so the return type is the anonymous object type
private fun foo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // Works
val x2 = publicFoo().x // ERROR: Unresolved reference 'x'
}
}
Just like Java's anonymous inner classes, code in object expressions can access variables from the enclosing scope. (Unlike Java,
this is not restricted to nal variables.)
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}
Object declarations
Singleton is a very useful pattern, and Kotlin (after Scala) makes it easy to declare singletons:
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}
This is called an object declaration, and it always has a name following the object keyword. Just like a variable declaration, an
object declaration is not an expression, and cannot be used on the right hand side of an assignment statement.
DataProviderManager.registerDataProvider(...)
73
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
NOTE: object declarations can't be local (i.e. be nested directly inside a function), but they can be nested into other object
declarations or non-inner classes.
Companion Objects
An object declaration inside a class can be marked with the companion keyword:
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
Members of the companion object can be called by using simply the class name as the qualier:
The name of the companion object can be omitted, in which case the name Companion will be used:
class MyClass {
companion object {
}
}
val x = MyClass.Companion
Note that, even though the members of companion objects look like static members in other languages, at runtime those are
still instance members of real objects, and can, for example, implement interfaces:
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
However, on the JVM you can have members of companion objects generated as real static methods and elds, if you use the
@JvmStatic annotation. See the Java interoperability section for more details.
There is one important semantic dierence between object expressions and object declarations:
object expressions are executed (and initialized) immediately, where they are used;
object declarations are initialized lazily, when accessed for the rst time;
a companion object is initialized when the corresponding class is loaded (resolved), matching the semantics of a Java static
initializer.
74
75
Delegation
Class Delegation
The Delegation pattern has proven to be a good alternative to implementation inheritance, and Kotlin supports it natively
requiring zero boilerplate code. A class Derived can inherit from an interface Base and delegate all of its public methods to a
specied object:
interface Base {
fun print()
}
The by-clause in the supertype list for Derived indicates that b will be stored internally in objects of Derived and the compiler
will generate all the methods of Base that forward to b .
Note that overrides work as you might expect: The compiler will use your override implementations instead of those in the
delegate object. If we were to add override fun print() { print("abc") } to Derived , the program would print "abc"
instead of "10".
76
Delegated Properties
There are certain common kinds of properties, that, though we can implement them manually every time we need them, would
be very nice to implement once and for all, and put into a library. Examples include:
lazy properties: the value gets computed only upon rst access;
observable properties: listeners get notied about changes to this property;
storing properties in a map, instead of a separate eld for each property.
class Example {
var p: String by Delegate()
}
The syntax is: val/var <property name>: <Type> by <expression> . The expression after by is the delegate , because get()
(and set() ) corresponding to the property will be delegated to its getValue() and setValue() methods. Property delegates
dont have to implement any interface, but they have to provide a getValue() function (and setValue() for var's). For
example:
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
When we read from p that delegates to an instance of Delegate , the getValue() function from Delegate is called, so that its
rst parameter is the object we read p from and the second parameter holds a description of p itself (e.g. you can take its
name). For example:
val e = Example()
println(e.p)
This prints:
Similarly, when we assign to p , the setValue() function is called. The rst two parameters are the same, and the third holds
the value being assigned:
e.p = "NEW"
This prints
The specication of the requirements to the delegated object can be found below.
Note that since Kotlin 1.1 you can declare a delegated property inside a function or code block, it shouldn't necessarily be a
member of a class. Below you can nd the example.
Standard Delegates
The Kotlin standard library provides factory methods for several useful kinds of delegates.
77
Lazy
lazy() is a function that takes a lambda and returns an instance of Lazy<T> which can serve as a delegate for implementing a
lazy property: the rst call to get() executes the lambda passed to lazy() and remembers the result, subsequent calls to
get() simply return the remembered result.
computed!
Hello
Hello
By default, the evaluation of lazy properties is synchronized: the value is computed only in one thread, and all threads will see
the same value. If the synchronization of initialization delegate is not required, so that multiple threads can execute it
simultaneously, pass LazyThreadSafetyMode.PUBLICATION as a parameter to the lazy() function. And if you're sure that the
initialization will always happen on a single thread, you can use LazyThreadSafetyMode.NONE mode, which doesn't incur any
thread-safety guarantees and the related overhead.
Observable
Delegates.observable() takes two arguments: the initial value and a handler for modications. The handler gets called every
time we assign to the property (after the assignment has been performed). It has three parameters: a property being assigned
to, the old value and the new one:
import kotlin.properties.Delegates
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}
If you want to be able to intercept an assignment and "veto" it, use vetoable() instead of observable() . The handler passed
to the vetoable is called before the assignment of a new property value has been performed.
78
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
Delegated properties take values from this map (by the string keys names of properties):
This works also for vars properties if you use a MutableMap instead of read-only Map :
The memoizedFoo variable will be computed on the rst access only. If someCondition fails, the variable won't be computed at
all.
For a read-only property (i.e. a val), a delegate has to provide a function named getValue that takes the following
parameters:
thisRef must be the same or a supertype of the property owner (for extension properties the type being extended);
property must be of type KProperty<*> or its supertype.
this function must return the same type as property (or its subtype).
For a mutable property (a var), a delegate has to additionally provide a function named setValue that takes the following
parameters:
79
getValue() and/or setValue() functions may be provided either as member functions of the delegate class or extension
functions. The latter is handy when you need to delegate property to an object which doesn't originally provide these functions.
Both of the functions need to be marked with the operator keyword.
The delegate class may implement one of the interfaces ReadOnlyProperty and ReadWriteProperty containing the required
operator methods. These interfaces are declared in the Kotlin standard library:
Translation Rules
Under the hood for every delegated property the Kotlin compiler generates an auxiliary property and delegates to it. For
instance, for the property prop the hidden property prop$delegate is generated, and the code of the accessors simply
delegates to this additional property:
class C {
var prop: Type by MyDelegate()
}
The Kotlin compiler provides all the necessary information about prop in the arguments: the rst argument this refers to an
instance of the outer class C and this::prop is a reection object of the KProperty type describing prop itself.
Note that the syntax this::prop to refer a bound callable reference in the code directly is available only since Kotlin 1.1.
By dening the provideDelegate operator you can extend the logic of creating the object to which the property
implementation is delegated. If the object used on the right hand side of by denes provideDelegate as a member or
extension function, that function will be called to create the property delegate instance.
One of the possible use cases of provideDelegate is to check property consistency when the property is created, not only in
its getter or setter.
For example, if you want to check the property name before binding, you can write something like this:
80
class ResourceDelegate<T> : ReadOnlyProperty<MyUI, T> {
override fun getValue(thisRef: MyUI, property: KProperty<*>): T { ... }
}
class MyUI {
fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... }
thisRef must be the same or a supertype of the property owner (for extension properties the type being extended);
property must be of type KProperty<*> or its supertype.
The provideDelegate method is called for each property during the creation of the MyUI instance, and it performs the
necessary validation right away.
Without this ability to intercept the binding between the property and its delegate, to achieve the same functionality you'd have
to pass the property name explicitly, which isn't very convenient:
In the generated code, the provideDelegate method is called to initialize the auxiliary prop$delegate property. Compare the
generated code for the property declaration val prop: Type by MyDelegate() with the generated code above (when the
provideDelegate method is not present):
81
class C {
var prop: Type by MyDelegate()
}
Note that the provideDelegate method aects only the creation of the auxiliary property and doesn't aect the code
generated for getter or setter.
82
Functions and Lambdas
Functions
Function Declarations
Functions in Kotlin are declared using the fun keyword:
Function Usage
Calling functions uses the traditional approach:
Parameters
Function parameters are dened using Pascal notation, i.e. name : type . Parameters are separated using commas. Each
parameter must be explicitly typed:
Default Arguments
Function parameters can have default values, which are used when a corresponding argument is omitted. This allows for a
reduced number of overloads compared to other languages:
Default values are dened using the = after type along with the value.
Overriding methods always use the same default parameter values as the base method. When overriding a method with default
parameters values, the default parameter values must be omitted from the signature:
83
open class A {
open fun foo(i: Int = 10) { ... }
}
class B : A() {
override fun foo(i: Int) { ... } // no default value allowed
}
If a default parameter precedes a parameter with no default value, the default value can be used only by calling the function with
named arguments:
But if a last argument lambda is passed to a function call outside the parentheses, passing no values for the default parameters
is allowed:
Named Arguments
Function parameters can be named when calling functions. This is very convenient when a function has a high number of
parameters or default ones.
reformat(str)
However, when calling it with non-default, the call would look something like:
With named arguments we can make the code much more readable:
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)
84
When a function is called with both positional and named arguments, all the positional arguments should be placed before the
rst named one. For example, the call f(1, y = 2) is allowed, but f(x = 1, 2) is not.
Variable number of arguments (vararg) can be passed in the named form by using the spread operator:
Note that the named argument syntax cannot be used when calling Java functions, because Java bytecode does not always
preserve names of function parameters.
Unit-returning functions
If a function does not return any useful value, its return type is Unit . Unit is a type with only one value - Unit . This value does
not have to be returned explicitly:
The Unit return type declaration is also optional. The above code is equivalent to:
Single-Expression functions
When a function returns a single expression, the curly braces can be omitted and the body is specied after a = symbol:
Explicitly declaring the return type is optional when this can be inferred by the compiler:
Functions with block body must always specify return types explicitly, unless it's intended for them to return Unit , in which case
it is optional. Kotlin does not infer return types for functions with block bodies because such functions may have complex control
ow in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler).
A parameter of a function (normally the last one) may be marked with vararg modier:
85
val list = asList(1, 2, 3)
Inside a function a vararg -parameter of type T is visible as an array of T , i.e. the ts variable in the example above has type
Array<out T> .
Only one parameter may be marked as vararg . If a vararg parameter is not the last one in the list, values for the following
parameters can be passed using the named argument syntax, or, if the parameter has a function type, by passing a lambda
outside parentheses.
When we call a vararg -function, we can pass arguments one-by-one, e.g. asList(1, 2, 3) , or, if we already have an array
and want to pass its contents to the function, we use the spread operator (prex the array with * ):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
In x notation
1 shl 2
// is the same as
1.shl(2)
Function Scope
In Kotlin functions can be declared at top level in a le, meaning you do not need to create a class to hold a function, like
languages such as Java, C# or Scala. In addition to top level functions, Kotlin functions can also be declared local, as member
functions and extension functions.
Local Functions
dfs(graph.vertices[0], HashSet())
}
Local function can access local variables of outer functions (i.e. the closure), so in the case above, the visited can be a local
variable:
86
fun dfs(graph: Graph) {
val visited = HashSet<Vertex>()
fun dfs(current: Vertex) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v)
}
dfs(graph.vertices[0])
}
Member Functions
class Sample() {
fun foo() { print("Foo") }
}
For more information on classes and overriding members see Classes and Inheritance.
Generic Functions
Functions can have generic parameters which are specied using angle brackets before the function name:
Inline Functions
Inline functions are explained here.
Extension Functions
Extension functions are explained in their own section.
This code calculates the xpoint of cosine, which is a mathematical constant. It simply calls Math.cos repeatedly starting at 1.0
until the result doesn't change any more, yielding a result of 0.7390851332151607. The resulting code is equivalent to this
more traditional style:
87
private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (x == y) return y
x = y
}
}
To be eligible for the tailrec modier, a function must call itself as the last operation it performs. You cannot use tail recursion
when there is more code after the recursive call, and you cannot use it within try/catch/nally blocks. Currently tail recursion is
only supported in the JVM backend.
88
Higher-Order Functions and Lambdas
Higher-Order Functions
A higher-order function is a function that takes functions as parameters, or returns a function. A good example of such a
function is lock() that takes a lock object and a function, acquires the lock, runs the function and releases the lock:
Let's examine the code above: body has a function type: () -> T , so it's supposed to be a function that takes no parameters
and returns a value of type T . It is invoked inside the try-block, while protected by the lock , and its result is returned by the
lock() function.
If we want to call lock() , we can pass another function to it as an argument (see function references):
Lambda expressions are described in more detail below, but for purposes of continuing this section, let's see a brief overview:
In Kotlin, there is a convention that if the last parameter to a function is a function, and you're passing a lambda expression as
the corresponding argument, you can specify it outside of parentheses:
lock (lock) {
sharedResource.operation()
}
Note that the parentheses in a call can be omitted entirely if the lambda is the only argument to that call.
89
it: implicit name of a single parameter
One other helpful convention is that if a function literal has only one parameter, its declaration may be omitted (along with the -
> ), and its name will be it :
ints.map { it * 2 }
If the lambda parameter is unused, you can place an underscore instead of its name:
Inline Functions
Sometimes it is benecial to enhance performance of higher-order functions using inline functions.
Function max is a higher-order function, i.e. it takes a function value as the second argument. This second argument is an
expression that is itself a function, i.e. a function literal. As a function, it is equivalent to:
Function Types
For a function to accept another function as a parameter, we have to specify a function type for that parameter. For example the
abovementioned function max is dened as follows:
The parameter less is of type (T, T) -> Boolean , i.e. a function that takes two parameters of type T and returns a
Boolean : true if the rst one is smaller than the second one.
In the body, line 4, less is used as a function: it is called by passing two arguments of type T .
A function type is written as above, or may have named parameters, if you want to document the meaning of each parameter.
90
To declare a nullable variable of a function type, enclose the entire function type in parentheses and put the question mark after
it:
The full syntactic form of lambda expressions, i.e. literals of function types, is as follows:
A lambda expression is always surrounded by curly braces, parameter declarations in the full syntactic form go inside curly
braces and have optional type annotations, the body goes after an -> sign. If the inferred return type of the lambda is not
Unit , the last (or possibly single) expression inside the lambda body is treated as the return value.
If we leave all the optional annotations out, what's left looks like this:
It's very common that a lambda expression has only one parameter. If Kotlin can gure the signature out itself, it allows us not to
declare the only parameter, and will implicitly declare it for us under the name it :
We can explicitly return a value from the lambda using the qualied return syntax. Otherwise, the value of the last expression is
implicitly returned. Therefore, the two following snippets are equivalent:
ints.filter {
val shouldFilter = it > 0
shouldFilter
}
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
Note that if a function takes another function as the last parameter, the lambda expression argument can be passed outside the
parenthesized argument list. See the grammar for callSux.
Anonymous Functions
One thing missing from the lambda expression syntax presented above is the ability to specify the return type of the function. In
most cases, this is unnecessary because the return type can be inferred automatically. However, if you do need to specify it
explicitly, you can use an alternative syntax: an anonymous function.
An anonymous function looks very much like a regular function declaration, except that its name is omitted. Its body can be
either an expression (as shown above) or a block:
The parameters and the return type are specied in the same way as for regular functions, except that the parameter types can
be omitted if they can be inferred from context:
91
ints.filter(fun(item) = item > 0)
The return type inference for anonymous functions works just like for normal functions: the return type is inferred automatically
for anonymous functions with an expression body and has to be specied explicitly (or is assumed to be Unit ) for anonymous
functions with a block body.
Note that anonymous function parameters are always passed inside the parentheses. The shorthand syntax allowing to leave
the function outside the parentheses works only for lambda expressions.
One other dierence between lambda expressions and anonymous functions is the behavior of non-local returns. A return
statement without a label always returns from the function declared with the fun keyword. This means that a return inside a
lambda expression will return from the enclosing function, whereas a return inside an anonymous function will return from the
anonymous function itself.
Closures
A lambda expression or anonymous function (as well as a local function and an object expression) can access its closure , i.e.
the variables declared in the outer scope. Unlike Java, the variables captured in the closure can be modied:
var sum = 0
ints.filter { it > 0 }.forEach {
sum += it
}
print(sum)
Kotlin provides the ability to call a function literal with a specied receiver object. Inside the body of the function literal, you can
call methods on that receiver object without any additional qualiers. This is similar to extension functions, which allow you to
access members of the receiver object inside the body of the function. One of the most important examples of their usage is
Type-safe Groovy-style builders.
The function literal can be called as if it were a method on the receiver object:
1.sum(2)
The anonymous function syntax allows you to specify the receiver type of a function literal directly. This can be useful if you need
to declare a variable of a function type with receiver, and to use it later.
A non-literal value of a function-with-receiver type can also be assigned or passed as an argument where an ordinary function is
expected that has an additional rst parameter of the receiver type, and vice versa. For example, the types String.(Int) ->
Boolean and (String, Int) -> Boolean are compatible:
Lambda expressions can be used as function literals with receiver when the receiver type can be inferred from context.
92
class HTML {
fun body() { ... }
}
93
Inline Functions
Using higher-order functions imposes certain runtime penalties: each function is an object, and it captures a closure, i.e. those
variables that are accessed in the body of the function. Memory allocations (both for function objects and classes) and virtual
calls introduce runtime overhead.
But it appears that in many cases this kind of overhead can be eliminated by inlining the lambda expressions. The functions
shown below are good examples of this situation. I.e., the lock() function could be easily inlined at call-sites. Consider the
following case:
lock(l) { foo() }
Instead of creating a function object for the parameter and generating a call, the compiler could emit the following code:
l.lock()
try {
foo()
}
finally {
l.unlock()
}
To make the compiler do this, we need to mark the lock() function with the inline modier:
The inline modier aects both the function itself and the lambdas passed to it: all of those will be inlined into the call site.
Inlining may cause the generated code to grow; however, if we do it in a reasonable way (i.e. avoiding inlining large functions), it
will pay o in performance, especially at "megamorphic" call-sites inside loops.
noinline
In case you want only some of the lambdas passed to an inline function to be inlined, you can mark some of your function
parameters with the noinline modier:
Inlinable lambdas can only be called inside the inline functions or passed as inlinable arguments, but noinline ones can be
manipulated in any way we like: stored in elds, passed around etc.
Note that if an inline function has no inlinable function parameters and no reied type parameters, the compiler will issue a
warning, since inlining such functions is very unlikely to be benecial (you can suppress the warning if you are sure the inlining is
needed using the annotation @Suppress("NOTHING_TO_INLINE") ).
Non-local returns
In Kotlin, we can only use a normal, unqualied return to exit a named function or an anonymous function. This means that to
exit a lambda, we have to use a label, and a bare return is forbidden inside a lambda, because a lambda can not make the
enclosing function return:
94
fun foo() {
ordinaryFunction {
return // ERROR: can not make `foo` return here
}
}
But if the function the lambda is passed to is inlined, the return can be inlined as well, so it is allowed:
fun foo() {
inlineFunction {
return // OK: the lambda is inlined
}
}
Such returns (located in a lambda, but exiting the enclosing function) are called non-local returns. We are used to this sort of
construct in loops, which inline functions often enclose:
Note that some inline functions may call the lambdas passed to them as parameters not directly from the function body, but
from another execution context, such as a local object or a nested function. In such cases, non-local control ow is also not
allowed in the lambdas. To indicate that, the lambda parameter needs to be marked with the crossinline modier:
break and continue are not yet available in inlined lambdas, but we are planning to support them too.
Here, we walk up a tree and use reection to check if a node has a certain type. Its all ne, but the call site is not very pretty:
treeNode.findParentOfType(MyTreeNode::class.java)
What we actually want is simply pass a type to this function, i.e. call it like this:
treeNode.findParentOfType<MyTreeNode>()
To enable this, inline functions support reied type parameters , so we can write something like this:
95
inline fun <reified T> TreeNode.findParentOfType(): T? {
var p = parent
while (p != null && p !is T) {
p = p.parent
}
return p as T?
}
We qualied the type parameter with the reified modier, now its accessible inside the function, almost as if it were a normal
class. Since the function is inlined, no reection is needed, normal operators like !is and as are working now. Also, we can
call it as mentioned above: myTree.findParentOfType<MyTreeNodeType>() .
Though reection may not be needed in many cases, we can still use it with a reied type parameter:
Normal functions (not marked as inline) can not have reied parameters. A type that does not have a run-time representation
(e.g. a non-reied type parameter or a ctitious type like Nothing ) can not be used as an argument for a reied type parameter.
You can also annotate an entire property, which marks both of its accessors as inline:
At the call site, inline accessors are inlined as regular inline functions.
This imposes certain risks of binary incompatibility caused by changes in the module that declares an inline function in case the
calling module is not re-compiled after the change.
To eliminate the risk of such incompatibility being introduced by a change in non-public API of a module, the public API inline
functions are not allowed to use non-public-API declarations, i.e. private and internal declarations and their parts, in their
bodies.
An internal declaration can be annotated with @PublishedApi , which allows its use in public API inline functions. When an
internal inline function is marked as @PublishedApi , its body is checked too, as if it were public.
96
Coroutines
Some APIs initiate long-running operations (such as network IO, le IO, CPU- or GPU-intensive work, etc) and require the caller to
block until they complete. Coroutines provide a way to avoid blocking a thread and replace it with a cheaper and more
controllable operation: suspension of a coroutine.
Coroutines simplify asynchronous programming by putting the complications into libraries. The logic of the program can be
expressed sequentially in a coroutine, and the underlying library will gure out the asynchrony for us. The library can wrap
relevant parts of the user code into callbacks, subscribe to relevant events, schedule execution on dierent threads (or even
dierent machines!), and the code remains as simple as if it was sequentially executed.
Many asynchronous mechanisms available in other languages can be implemented as libraries using Kotlin coroutines. This
includes async/await from C# and ECMAScript, channels and select from Go, and generators/yield from C# and Python. See
the description below for libraries providing such constructs.
Blocking vs Suspending
Basically, coroutines are computations that can be suspended without blocking a thread. Blocking threads is often expensive,
especially under high load, because only a relatively small number of threads is practical to keep around, so blocking one of
them leads to some important work being delayed.
Coroutine suspension is almost free, on the other hand. No context switch or any other involvement of the OS is required. And
on top of that, suspension can be controlled by a user library to a large extent: as library authors, we can decide what happens
upon a suspension and optimize/log/intercept according to our needs.
Another dierence is that coroutines can not be suspended at random instructions, but rather only at so called suspension
points , which are calls to specially marked functions.
Suspending functions
A suspension happens when we call a function marked with the special modier, suspend :
Such functions are called suspending functions , because calls to them may suspend a coroutine (the library can decide to
proceed without suspension, if the result for the call in question is already available). Suspending functions can take parameters
and return values in the same manner as regular functions, but they can only be called from coroutines and other suspending
functions. In fact, to start a coroutine, there must be at least one suspending function, and it is usually anonymous (i.e. it is a
suspending lambda). Let's look at an example, a simplied async() function (from the kotlinx.coroutines library):
Here, async() is a regular function (not a suspending function), but the block parameter has a function type with the
suspend modier: suspend () -> T . So, when we pass a lambda to async() , it is a suspending lambda, and we can call a
suspending function from it:
async {
doSomething(foo)
...
}
Note: currently, suspending function types cannot be used as supertypes, and anonymous suspending functions are
currently not supported.
97
To continue the analogy, await() can be a suspending function (hence also callable from within an async {} block) that
suspends a coroutine until some computation is done and returns its result:
async {
...
val result = computation.await()
...
}
More information on how actual async/await functions work in kotlinx.coroutines can be found here.
Note that suspending functions await() and doSomething() can not be called from a regular function like main() :
Also note that suspending functions can be virtual, and when overriding them, the suspend modier has to be specied:
interface Base {
suspend fun foo()
}
@RestrictsSuspension annotation
Extension functions (and lambdas) can also be marked suspend , just like regular ones. This enables creation of DSLs and other
APIs that users can extend. In some cases the library author needs to prevent the user from adding new ways of suspending a
coroutine.
To achieve this, the @RestrictsSuspension annotation may be used. When a receiver class or interface R is annotated with it,
all suspending extensions are required to delegate to either members of R or other extensions to it. Since extensions can't
delegate to each other indenitely (the program would not terminate), this guarantees that all suspensions happen through
calling members of R that the author of the library can fully control.
This is relevant in the rare cases when every suspension is handled in a special way in the library. For example, when
implementing generators through the buildSequence() function described below, we need to make sure that any suspending
call in the coroutine ends up calling either yield() or yieldAll() and not any other function. This is why SequenceBuilder is
annotated with @RestrictsSuspension :
@RestrictsSuspension
public abstract class SequenceBuilder<in T> {
...
}
Coroutines are completely implemented through a compilation technique (no support from the VM or OS side is required), and
suspension works through code transformation. Basically, every suspending function (optimizations may apply, but we'll not go
into this here) is transformed to a state machine where states correspond to suspending calls. Right before a suspension, the
next state is stored in a eld of a compiler-generated class along with relevant local variables, etc. Upon resumption of that
coroutine, local variables are restored and the state machine proceeds from the state right after suspension.
98
A suspended coroutine can be stored and passed around as an object that keeps its suspended state and locals. The type of
such objects is Continuation , and the overall code transformation described here corresponds to the classical Continuation-
passing style. Consequently, suspending functions take an extra parameter of type Continuation under the hood.
More details on how coroutines work may be found in this design document. Similar descriptions of async/await in other
languages (such as C# or ECMAScript 2016) are relevant here, although the language features they implement may not be as
general as Kotlin coroutines.
Due to its experimental status, the coroutine-related API in the Standard Library is put under the
kotlin.coroutines.experimental package. When the design is nalized and the experimental status lifted, the nal API will
be moved to kotlin.coroutines , and the experimental package will be kept around (probably in a separate artifact) for
backward compatibility.
IMPORTANT NOTE: We advise library authors to follow the same convention: add the "experimental" (e.g.
com.example.experimental ) sux to your packages exposing coroutine-based APIs so that your library remains binary
compatible. When the nal API is released, follow these steps:
Standard APIs
Coroutines come in three main ingredients:
Low-level API is relatively small and should never be used other than for creating higher-level libraries. It consists of two main
packages:
startCoroutine(),
suspendCoroutine();
More details about the usage of these APIs can be found here.
buildSequence()
buildIterator()
These are shipped within kotlin-stdlib because they are related to sequences. In fact, these functions (and we can limit
ourselves to buildSequence() alone here) implement generators , i.e. provide a way to cheaply build a lazy sequence:
99
val fibonacciSeq = buildSequence {
var a = 0
var b = 1
yield(1)
while (true) {
yield(a + b)
val tmp = a + b
a = b
b = tmp
}
}
This generates a lazy, potentially innite Fibonacci sequence by creating a coroutine that yields consecutive Fibonacci numbers
by calling the yield() function. When iterating over such a sequence every step of the iterator executes another portion of the
coroutine that generates the next number. So, we can take any nite list of numbers out of this sequence, e.g.
fibonacciSeq.take(8).toList() results in [1, 1, 2, 3, 5, 8, 13, 21] . And coroutines are cheap enough to make this
practical.
To demonstrate the real laziness of such a sequence, let's print some debug output inside a call to buildSequence() :
Running the code above prints the rst three elements. The numbers are interleaved with STEP s in the generating loop. This
means that the computation is lazy indeed. To print 1 we only execute until the rst yield(i) , and print START along the way.
Then, to print 2 we need to proceed to the next yield(i) , and this prints STEP . Same for 3 . And the next STEP never gets
printed (as well as END ), because we never requested further elements of the sequence.
To yield a collection (or sequence) of values at once, the yieldAll() function is available:
One can add custom yielding logic to buildSequence() by writing suspending extensions to the SequenceBuilder class (that
bears the @RestrictsSuspension annotation described above):
100
Other high-level APIs: kotlinx.coroutines
Only core APIs related to coroutines are available from the Kotlin Standard Library. This mostly consists of core primitives and
interfaces that all coroutine-based libraries are likely to use.
Most application-level APIs based on coroutines are released as a separate library: kotlinx.coroutines. This library covers
this module includes Go-like channels that support select and other convenient primitives,
These libraries serve as both convenient APIs that make common tasks easy and end-to-end examples of how to build
coroutine-based libraries.
101
Other
Destructuring Declarations
Sometimes it is convenient to destructure an object into a number of variables, for example:
This syntax is called a destructuring declaration. A destructuring declaration creates multiple variables at once. We have
declared two new variables: name and age , and can use them independently:
println(name)
println(age)
The component1() and component2() functions are another example of the principle of conventions widely used in Kotlin (see
operators like + and * , for-loops etc.). Anything can be on the right-hand side of a destructuring declaration, as long as the
required number of component functions can be called on it. And, of course, there can be component3() and component4()
and so on.
Note that the componentN() functions need to be marked with the operator keyword to allow using them in a destructuring
declaration.
Variables a and b get the values returned by component1() and component2() called on elements of the collection.
Since data classes automatically declare componentN() functions, destructuring declarations work here.
NOTE: we could also use the standard class Pair and have function() return Pair<Int, Status> , but it's often better to
have your data named properly.
102
Example: Destructuring Declarations and Maps
Probably the nicest way to traverse a map is this:
present each of the elements as a pair by providing functions component1() and component2() .
So you can freely use destructuring declarations in for-loops with maps (as well as collections of data class instances etc).
The componentN() operator functions are not called for the components that are skipped in this way.
Note the dierence between declaring two parameters and declaring a destructuring pair instead of a parameter:
If a component of the destructured parameter is unused, you can replace it with the underscore to avoid inventing its name:
You can specify the type for the whole destructured parameter or for a specic component separately:
103
Collections: List, Set, Map
Unlike many languages, Kotlin distinguishes between mutable and immutable collections (lists, sets, maps, etc). Precise control
over exactly when collections can be edited is useful for eliminating bugs, and for designing good APIs.
It is important to understand up front the dierence between a read-only view of a mutable collection, and an actually immutable
collection. Both are easy to create, but the type system doesn't express the dierence, so keeping track of that (if it's relevant)
is up to you.
The Kotlin List<out T> type is an interface that provides read-only operations like size , get and so on. Like in Java, it inherits
from Collection<T> and that in turn inherits from Iterable<T> . Methods that change the list are added by the
MutableList<T> interface. This pattern holds also for Set<out T>/MutableSet<T> and Map<K, out V>/MutableMap<K, V> .
We can see basic usage of the list and set types below:
Kotlin does not have dedicated syntax constructs for creating lists or sets. Use methods from the standard library, such as
listOf() , mutableListOf() , setOf() , mutableSetOf() . Map creation in NOT performance-critical code can be
accomplished with a simple idiom: mapOf(a to b, c to d) .
Note that the readOnlyView variable points to the same list and changes as the underlying list changes. If the only references
that exist to a list are of the read-only variety, we can consider the collection fully immutable. A simple way to create such a
collection is like this:
Currently, the listOf method is implemented using an array list, but in future more memory-ecient fully immutable collection
types could be returned that exploit the fact that they know they can't change.
Note that the read-only types are covariant. That means, you can take a List<Rectangle> and assign it to List<Shape>
assuming Rectangle inherits from Shape. This wouldn't be allowed with the mutable collection types because it would allow for
failures at runtime.
Sometimes you want to return to the caller a snapshot of a collection at a particular point in time, one that's guaranteed to not
change:
class Controller {
private val _items = mutableListOf<String>()
val items: List<String> get() = _items.toList()
}
The toList extension method just duplicates the lists items, thus, the returned list is guaranteed to never change.
There are various useful extension methods on lists and sets that are worth being familiar with:
104
val items = listOf(1, 2, 3, 4)
items.first() == 1
items.last() == 4
items.filter { it % 2 == 0 } // returns [2, 4]
as well as all the utilities you would expect such as sort, zip, fold, reduce and so on.
Maps follow the same pattern. They can be easily instantiated and accessed like this:
105
Ranges
Range expressions are formed with rangeTo functions that have the operator form .. which is complemented by in and !in.
Range is dened for any comparable type, but for integral primitive types it has an optimized implementation. Here are some
examples of using ranges:
Integral type ranges ( IntRange , LongRange , CharRange ) have an extra feature: they can be iterated over. The compiler takes
care of converting this analogously to Java's indexed for-loop, without extra overhead:
What if you want to iterate over numbers in reverse order? It's simple. You can use the downTo() function dened in the
standard library:
Is it possible to iterate over numbers with arbitrary step, not equal to 1? Sure, the step() function will help you:
To create a range which does not include its end element, you can use the until function:
How it works
Ranges implement a common interface in the library: ClosedRange<T> .
ClosedRange<T> denotes a closed interval in the mathematical sense, dened for comparable types. It has two endpoints:
start and endInclusive , which are included in the range. The main operation is contains , usually used in the form of in/!in
operators.
A progression is a subtype of Iterable<N> , where N is Int , Long or Char respectively, so it can be used in for-loops and
functions like map , filter , etc. Iteration over Progression is equivalent to an indexed for-loop in Java/JavaScript:
For integral types, the .. operator creates an object which implements both ClosedRange<T> and *Progression . For
example, IntRange implements ClosedRange<Int> and extends IntProgression , thus all operations dened for
IntProgression are available for IntRange as well. The result of the downTo() and step() functions is always a
*Progression .
106
Progressions are constructed with the fromClosedRange function dened in their companion objects:
The last element of the progression is calculated to nd maximum value not greater than the end value for positive step or
minimum value not less than the end value for negative step such that (last - first) % step == 0 .
Utility functions
rangeTo()
The rangeTo() operators on integral types simply call the constructors of *Range classes, e.g.:
class Int {
//...
operator fun rangeTo(other: Long): LongRange = LongRange(this, other)
//...
operator fun rangeTo(other: Int): IntRange = IntRange(this, other)
//...
}
Floating point numbers ( Double , Float ) do not dene their rangeTo operator, and the one provided by the standard library
for generic Comparable types is used instead:
downTo()
The downTo() extension function is dened for any pair of integral types, here are two examples:
reversed()
The reversed() extension functions are dened for each *Progression classes, and all of them return reversed
progressions:
step()
step() extension functions are dened for *Progression classes, all of them return progressions with modied step values
(function parameter). The step value is required to be always positive, therefore this function never changes the direction of
iteration:
107
fun IntProgression.step(step: Int): IntProgression {
if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step")
return IntProgression.fromClosedRange(first, last, if (this.step > 0) step else -step)
}
Note that the last value of the returned progression may become dierent from the last value of the original progression in
order to preserve the invariant (last - first) % step == 0 . Here is an example:
108
Type Checks and Casts: 'is' and 'as'
if (obj is String) {
print(obj.length)
}
Smart Casts
In many cases, one does not need to use explicit cast operators in Kotlin, because the compiler tracks the is -checks and
explicit casts for immutable values and inserts (safe) casts automatically when needed:
The compiler is smart enough to know a cast to be safe if a negative check leads to a return:
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
Note that smart casts do not work when the compiler cannot guarantee that the variable cannot change between the check
and the usage. More specically, smart casts are applicable according to the following rules:
109
var properties - never (because the variable can be modied at any time by other code).
Note that null cannot be cast to String as this type is not nullable, i.e. if y is null, the code above throws an exception. In
order to match Java cast semantics we have to have nullable type at cast right hand side, like:
Note that despite the fact that the right-hand side of as? is a non-null type String the result of the cast is nullable.
110
This Expression
To denote the current receiver, we use this expressions:
In an extension function or a function literal with receiver this denotes the receiver parameter that is passed on the left-
hand side of a dot.
If this has no qualiers, it refers to the innermost enclosing scope . To refer to this in other scopes, label qualiers are used:
Quali ed this
To access this from an outer scope (a class, or extension function, or labeled function literal with receiver) we write
this@label where @label is a label on the scope this is meant to be from:
111
Equality
In Kotlin there are two types of equality:
Referential equality
Referential equality is checked by the === operation (and its negated counterpart !== ). a === b evaluates to true if and only if
a and b point to the same object.
Structural equality
Structural equality is checked by the == operation (and its negated counterpart != ). By convention, an expression like a == b
is translated to:
I.e. if a is not null , it calls the equals(Any?) function, otherwise (i.e. a is null ) it checks that b is referentially equal to
null .
Note that there's no point in optimizing your code when comparing to null explicitly: a == null will be automatically
translated to a === null .
Otherwise, the structural equality is used, which disagrees with the standard so that NaN is equal to itself, and -0.0 is not
equal to 0.0 .
112
Operator overloading
Kotlin allows us to provide implementations for a predened set of operators on our types. These operators have xed symbolic
representation (like + or * ) and xed precedence. To implement an operator, we provide a member function or an extension
function with a xed name, for the corresponding type, i.e. left-hand side type for binary operations and argument type for unary
ones. Functions that overload operators need to be marked with the operator modier.
Further we describe the conventions that regulate operator overloading for dierent operators.
Unary operations
Expression Translated to
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
This table says that when the compiler processes, for example, an expression +a , it performs the following steps:
Looks up a function unaryPlus() with the operator modier and no parameters for the receiver T , i.e. a member
function or an extension function;
If the function is absent or ambiguous, it is a compilation error;
If the function is present and its return type is R , the expression +a has type R ;
Note that these operations, as well as all the others, are optimized for Basic types and do not introduce overhead of function
calls for them.
As an example, here's how you can overload the unary minus operator:
Expression Translated to
a++ a.inc() + see below
a-- a.dec() + see below
The inc() and dec() functions must return a value, which will be assigned to the variable on which the ++ or -- operation
was used. They shouldn't mutate the object on which the inc or dec was invoked.
The compiler performs the following steps for resolution of an operator in the postx form, e.g. a++ :
Looks up a function inc() with the operator modier and no parameters, applicable to the receiver of type T ;
Checks that the return type of the function is a subtype of T .
113
For a-- the steps are completely analogous.
For the prex forms ++a and --a resolution works the same way, and the eect is:
Binary operations
Arithmetic operators
Expression Translated to
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b), a.mod(b) (deprecated)
a..b a.rangeTo(b)
For the operations in this table, the compiler just resolves the expression in the Translated to column.
Note that the rem operator is supported since Kotlin 1.1. Kotlin 1.0 uses the mod operator, which is deprecated in Kotlin 1.1.
Example
Below is an example Counter class that starts at a given value and can be incremented using the overloaded + operator:
'In' operator
Expression Translated to
a in b b.contains(a)
a !in b !b.contains(a)
For in and !in the procedure is the same, but the order of arguments is reversed.
Expression Translated to
a[i] a.get(i)
a[i, j] a.get(i, j)
a[i_1, ..., i_n] a.get(i_1, ..., i_n)
a[i] = b a.set(i, b)
a[i, j] = b a.set(i, j, b)
a[i_1, ..., i_n] = b a.set(i_1, ..., i_n, b)
Square brackets are translated to calls to get and set with appropriate numbers of arguments.
Invoke operator
Expression Translated to
114
a()
Expression a.invoke()
Translated to
a(i) a.invoke(i)
a(i, j) a.invoke(i, j)
a(i_1, ..., i_n) a.invoke(i_1, ..., i_n)
Augmented assignments
Expression Translated to
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.remAssign(b), a.modAssign(b) (deprecated)
For the assignment operations, e.g. a += b , the compiler performs the following steps:
Otherwise, try to generate code for a = a + b (this includes a type check: the type of a + b must be a subtype of a ).
Expression Translated to
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ?: (b === null))
Note : === and !== (identity checks) are not overloadable, so no conventions exist for them.
The == operation is special: it is translated to a complex expression that screens for null 's. null == null is always true, and
x == null for a non-null x is always false and won't invoke x.equals() .
Comparison operators
Expression Translated to
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0
All comparisons are translated into calls to compareTo , that is required to return Int .
provideDelegate , getValue and setValue operator functions are described in Delegated properties.
115
Null Safety
One of the most common pitfalls in many programming languages, including Java, is that of accessing a member of a null
reference, resulting in a null reference exception. In Java this would be the equivalent of a NullPointerException or NPE for
short.
Kotlin's type system is aimed to eliminate NullPointerException 's from our code. The only possible causes of NPE's may be
In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that can not
(non-null references). For example, a regular variable of type String can not hold null:
Now, if you call a method or access a property on a , it's guaranteed not to cause an NPE, so you can safely say:
val l = a.length
But if you want to access the same property on b , that would not be safe, and the compiler reports an error:
But we still need to access that property, right? There are a few ways of doing that.
The compiler tracks the information about the check you performed, and allows the call to length inside the if. More complex
conditions are supported as well:
Note that this only works where b is immutable (i.e. a local variable which is not modied between the check and the usage or
a member val which has a backing eld and is not overridable), because otherwise it might happen that b changes to null
after the check.
116
Safe Calls
Your second option is the safe call operator, written ?. :
b?.length
This returns b.length if b is not null, and null otherwise. The type of this expression is Int? .
Safe calls are useful in chains. For example, if Bob, an Employee, may be assigned to a Department (or not), that in turn may
have another Employee as a department head, then to obtain the name of Bob's department head (if any), we write the
following:
bob?.department?.head?.name
To perform a certain operation only for non-null values, you can use the safe call operator together with let:
Elvis Operator
When we have a nullable reference r , we can say "if r is not null, use it, otherwise use some non-null value x ":
Along with the complete if-expression, this can be expressed with the Elvis operator, written ?: :
val l = b?.length ?: -1
If the expression to the left of ?: is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note
that the right-hand side expression is evaluated only if the left-hand side is null.
Note that, since throw and return are expressions in Kotlin, they can also be used on the right hand side of the elvis operator.
This can be very handy, for example, for checking function arguments:
The !! Operator
The third option is for NPE-lovers. We can write b!! , and this will return a non-null value of b (e.g., a String in our example) or
throw an NPE if b is null:
val l = b!!.length
Thus, if you want an NPE, you can have it, but you have to ask for it explicitly, and it does not appear out of the blue.
Safe Casts
Regular casts may result into a ClassCastException if the object is not of the target type. Another option is to use safe casts
that return null if the attempt was not successful:
117
val aInt: Int? = a as? Int
118
Exceptions
Exception Classes
All exception classes in Kotlin are descendants of the class Throwable . Every exception has a message, stack trace and an
optional cause.
try {
// some code
}
catch (e: SomeException) {
// handler
}
finally {
// optional finally block
}
There may be zero or more catch blocks. finally blocks may be omitted. However at least one catch or finally block should
be present.
Try is an expression
The returned value of a try-expression is either the last expression in the try block or the last expression in the catch block (or
blocks). Contents of the finally block do not aect the result of the expression.
Checked Exceptions
Kotlin does not have checked exceptions. There are many reasons for this, but we will provide a simple example.
What does this signature say? It says that every time I append a string to something (a StringBuilder , some kind of a log, a
console, etc.) I have to catch those IOExceptions . Why? Because it might be performing IO ( Writer also implements
Appendable ) So it results into this kind of code all over the place:
try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}
And this is no good, see Eective Java, Item 65: Don't ignore exceptions .
119
Examination of small programs leads to the conclusion that requiring exception specications could both enhance
developer productivity and enhance code quality, but experience with large software projects suggests a dierent result
decreased productivity and little or no increase in code quality.
The type of the throw expression is the special type Nothing . The type has no values and is used to mark code locations that
can never be reached. In your own code, you can use Nothing to mark a function that never returns:
When you call this function, the compiler will know that the execution doesn't continue beyond the call:
Another case where you may encounter this type is type inference. The nullable variant of this type, Nothing? , has exactly one
possible value, which is null . If you use null to initialize a value of an inferred type and there's no other information that can
be used to determine a more specic type, the compiler will infer the Nothing? type:
Java Interoperability
Please see the section on exceptions in the Java Interoperability section for information about Java interoperability.
120
Annotations
Annotation Declaration
Annotations are means of attaching metadata to code. To declare an annotation, put the annotation modier in front of a class:
Additional attributes of the annotation can be specied by annotating the annotation class with meta-annotations:
@Target species the possible kinds of elements which can be annotated with the annotation (classes, functions,
properties, expressions etc.);
@Retention species whether the annotation is stored in the compiled class les and whether it's visible through reection
at runtime (by default, both are true);
@Repeatable allows using the same annotation on a single element multiple times;
@MustBeDocumented species that the annotation is part of the public API and should be included in the class or method
signature shown in the generated API documentation.
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
Usage
If you need to annotate the primary constructor of a class, you need to add the constructor keyword to the constructor
declaration, and add the annotations before it:
class Foo {
var x: MyDependency? = null
@Inject set
}
Constructors
121
classes ( Foo::class );
enums;
other annotations;
arrays of the types listed above.
Annotation parameters cannot have nullable types, because the JVM does not support storing null as a value of an annotation
attribute.
If an annotation is used as a parameter of another annotation, its name is not prexed with the @ character:
If you need to specify a class as an argument of an annotation, use a Kotlin class (KClass). The Kotlin compiler will automatically
convert it to a Java class, so that the Java code will be able to see the annotations and arguments normally.
import kotlin.reflect.KClass
Lambdas
Annotations can also be used on lambdas. They will be applied to the invoke() method into which the body of the lambda is
generated. This is useful for frameworks like Quasar, which uses annotations for concurrency control.
The same syntax can be used to annotate the entire le. To do this, put an annotation with the target file at the top level of a
le, before the package directive or before all imports if the le is in the default package:
@file:JvmName("Foo")
package org.jetbrains.demo
If you have multiple annotations with the same target, you can avoid repeating the target by adding brackets after the target and
putting all the annotations inside the brackets:
122
class Example {
@set:[Inject VisibleForTesting]
var collaborator: Collaborator
}
file ;
delegate (the eld storing the delegate instance for a delegated property).
To annotate the receiver parameter of an extension function, use the following syntax:
If you don't specify a use-site target, the target is chosen according to the @Target annotation of the annotation being used. If
there are multiple applicable targets, the rst applicable target from the following list is used:
param ;
property ;
field .
Java Annotations
Java annotations are 100% compatible with Kotlin:
import org.junit.Test
import org.junit.Assert.*
import org.junit.Rule
import org.junit.rules.*
class Tests {
// apply @Rule annotation to property getter
@get:Rule val tempFolder = TemporaryFolder()
Since the order of parameters for an annotation written in Java is not dened, you can't use a regular function call syntax for
passing the arguments. Instead, you need to use the named argument syntax:
// Java
public @interface Ann {
int intValue();
String stringValue();
}
123
// Kotlin
@Ann(intValue = 1, stringValue = "abc") class C
Just like in Java, a special case is the value parameter; its value can be specied without an explicit name:
// Java
public @interface AnnWithValue {
String value();
}
// Kotlin
@AnnWithValue("abc") class C
If the value argument in Java has an array type, it becomes a vararg parameter in Kotlin:
// Java
public @interface AnnWithArrayValue {
String[] value();
}
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C
For other arguments that have an array type, you need to use arrayOf explicitly:
// Java
public @interface AnnWithArrayMethod {
String[] names();
}
// Kotlin
@AnnWithArrayMethod(names = arrayOf("abc", "foo", "bar")) class C
// Java
public @interface Ann {
int value();
}
// Kotlin
fun foo(ann: Ann) {
val i = ann.value
}
124
Re ection
Reection is a set of language and library features that allows for introspecting the structure of your own program at runtime.
Kotlin makes functions and properties rst-class citizens in the language, and introspecting them (i.e. learning a name or a type
of a property or function at runtime) is closely intertwined with simply using a functional or reactive style.
On the Java platform, the runtime component required for using the re ection features is distributed as a separate JAR
le (kotlin-reflect.jar). This is done to reduce the required size of the runtime library for applications that do not
use re ection features. If you do use re ection, please make sure that the .jar le is added to the classpath of your
project.
Class References
The most basic reection feature is getting the runtime reference to a Kotlin class. To obtain the reference to a statically known
Kotlin class, you can use the class literal syntax:
val c = MyClass::class
Note that a Kotlin class reference is not the same as a Java class reference. To obtain a Java class reference, use the .java
property on a KClass instance.
You obtain the reference to an exact class of an object, for instance GoodWidget or BadWidget , despite the type of the receiver
expression ( Widget ).
Function References
When we have a named function declared like this:
We can easily call it directly ( isOdd(5) ), but we can also pass it as a value, e.g. to another function. To do this, we use the ::
operator:
:: can be used with overloaded functions when the expected type is known from the context. For example:
Alternatively, you can provide the necessary context by storing the method reference in a variable with an explicitly specied
type:
125
val predicate: (String) -> Boolean = ::isOdd // refers to isOdd(x: String)
If we need to use a member of a class, or an extension function, it needs to be qualied. e.g. String::toCharArray gives us
an extension function for type String : String.() -> CharArray .
fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
return { x -> f(g(x)) }
}
It returns a composition of two functions passed to it: compose(f, g) = f(g(*)) . Now, you can apply it to callable references:
Property References
To access properties as rst-class objects in Kotlin, we can also use the :: operator:
val x = 1
The expression ::x evaluates to a property object of type KProperty<Int> , which allows us to read its value using get() or
retrieve the property name using the name property. For more information, please refer to the docs on the KProperty class.
For a mutable property, e.g. var y = 1 , ::y returns a value of type KMutableProperty<Int>, which has a set() method:
var y = 1
126
For an extension property:
On the Java platform, standard library contains extensions for reection classes that provide a mapping to and from Java
reection objects (see package kotlin.reflect.jvm ). For example, to nd a backing eld or a Java method that serves as a
getter for a Kotlin property, you can say something like this:
import kotlin.reflect.jvm.*
To get the Kotlin class corresponding to a Java class, use the .kotlin extension property:
Constructor References
Constructors can be referenced just like methods and properties. They can be used wherever an object of function type is
expected that takes the same parameters as the constructor and returns an object of the appropriate type. Constructors are
referenced by using the :: operator and adding the class name. Consider the following function that expects a function
parameter with no parameters and return type Foo :
class Foo
Using ::Foo , the zero-argument constructor of the class Foo, we can simply call it like this:
function(::Foo)
Instead of calling the method matches directly we are storing a reference to it. Such reference is bound to its receiver. It can be
called directly (like in the example above) or used whenever an expression of function type is expected:
127
val strings = listOf("abc", "124", "a70")
println(strings.filter(numberRegex::matches)) // prints "[124]"
Compare the types of bound and the corresponding unbound references. Bound callable reference has its receiver "attached"
to it, so the type of the receiver is no longer a parameter:
128
Type-Safe Builders
The concept of builders is rather popular in the Groovy community. Builders allow for dening data in a semi-declarative way.
Builders are good for generating XML, laying out UI components, describing 3D scenes and more
For many use cases, Kotlin allows to type-check builders, which makes them even more attractive than the dynamically-typed
implementation made in Groovy itself.
For the rest of the cases, Kotlin supports Dynamic types builders.
// mixed content
p {
+"This is some"
b {+"mixed"}
+"text. For more see the"
a(href = "http://kotlinlang.org") {+"Kotlin"}
+"project"
}
p {+"some text"}
// content generated by
p {
for (arg in args)
+arg
}
}
}
This is completely legitimate Kotlin code. You can play with this code online (modify it and run in the browser) here.
How it works
Let's walk through the mechanisms of implementing type-safe builders in Kotlin. First of all we need to dene the model we want
to build, in this case we need to model HTML tags. It is easily done with a bunch of classes. For example, HTML is a class that
describes the <html> tag, i.e. it denes children like <head> and <body> . (See its declaration below.)
Now, let's recall why we can say something like this in the code:
html {
// ...
}
html is actually a function call that takes a lambda expression as an argument. This function is dened as follows:
129
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
This function takes one parameter named init , which is itself a function. The type of the function is HTML.() -> Unit , which
is a function type with receiver. This means that we need to pass an instance of type HTML (a receiver) to the function, and we
can call members of that instance inside the function. The receiver can be accessed through the this keyword:
html {
this.head { /* ... */ }
this.body { /* ... */ }
}
Now, this can be omitted, as usual, and we get something that looks very much like a builder already:
html {
head { /* ... */ }
body { /* ... */ }
}
So, what does this call do? Let's look at the body of html function as dened above. It creates a new instance of HTML , then it
initializes it by calling the function that is passed as an argument (in our example this boils down to calling head and body on
the HTML instance), and then it returns this instance. This is exactly what a builder should do.
The head and body functions in the HTML class are dened similarly to html . The only dierence is that they add the built
instances to the children collection of the enclosing HTML instance:
Actually these two functions do just the same thing, so we can have a generic version, initTag :
130
One other thing to be discussed here is how we add text to tag bodies. In the example above we say something like:
html {
head {
title {+"XML encoding with Kotlin"}
}
// ...
}
So basically, we just put a string inside a tag body, but there is this little + in front of it, so it is a function call that invokes a prex
unaryPlus() operation. That operation is actually dened by an extension function unaryPlus() that is a member of the
TagWithText abstract class (a parent of Title ):
fun String.unaryPlus() {
children.add(TextElement(this))
}
So, what the prex + does here is it wraps a string into an instance of TextElement and adds it to the children collection, so
that it becomes a proper part of the tag tree.
All this is dened in a package com.example.html that is imported at the top of the builder example above. In the last section
you can read through the full denition of this package.
html {
head {
head {} // should be forbidden
}
// ...
}
In this example only members of the nearest implicit receiver this@head must be available; head() is a member of the outer
receiver this@html , so it must be illegal to call it.
To address this problem, in Kotlin 1.1 a special mechanism to control receiver scope was introduced.
To make the compiler start controlling scopes we only have to annotate the types of all receivers used in the DSL with the same
marker annotation. For instance, for HTML Builders we declare an annotation @HTMLTagMarker :
@DslMarker
annotation class HtmlTagMarker
An annotation class is called a DSL marker if it is annotated with the @DslMarker annotation.
In our DSL all the tag classes extend the same superclass Tag . It's enough to annotate only the superclass with
@HtmlTagMarker and after that the Kotlin compiler will treat all the inherited classes as annotated:
@HtmlTagMarker
abstract class Tag(val name: String) { ... }
We don't have to annotate the HTML or Head classes with @HtmlTagMarker because their superclass is already annotated:
131
After we've added this annotation, the Kotlin compiler knows which implicit receivers are part of the same DSL and allows to call
members of the nearest receivers only:
html {
head {
head { } // error: a member of outer receiver
}
// ...
}
Note that it's still possible to call the members of the outer receiver, but to do that you have to specify this receiver explicitly:
html {
head {
this@html.head { } // possible
}
// ...
}
Note that the @DslMarker annotation is available only since Kotlin 1.1.
package com.example.html
interface Element {
fun render(builder: StringBuilder, indent: String)
}
@DslMarker
annotation class HtmlTagMarker
@HtmlTagMarker
abstract class Tag(val name: String) : Element {
val children = arrayListOf<Element>()
val attributes = hashMapOf<String, String>()
132
}
return builder.toString()
}
class A : BodyTag("a") {
var href: String
get() = attributes["href"]!!
set(value) {
attributes["href"] = value
}
}
133
Type aliases
Type aliases provide alternative names for existing types. If the type name is too long you can introduce a dierent shorter name
and use the new one instead.
It's useful to shorten long generic types. For instance, it's often tempting to shrink collection types:
You can have new names for inner and nested classes:
class A {
inner class Inner
}
class B {
inner class Inner
}
Type aliases do not introduce new types. They are equivalent to the corresponding underlying types. When you add typealias
Predicate<T> and use Predicate<Int> in your code, the Kotlin compiler always expand it to (Int) -> Boolean . Thus you
can pass a variable of your type whenever a general function type is required and vice versa:
134
Multiplatform Projects (Preview)
Multiplatform projects are a new experimental feature in Kotlin 1.2. All of the language and tooling features described
in this document are subject to change in future Kotlin versions.
A Kotlin multiplatform project allows you to compile the same code to multiple target platforms. At this time supported target
platforms are the JVM and JS, with Native to be added later.
A common module contains code that is not specic to any platform, as well as declarations without implementation of
platform-dependent APIs. Those declarations allow common code to depend on platform-specic implementations.
A platform module contains implementations of platform-dependent declarations in the common module for a specic
platform, as well as other platform-dependent code. A platform module is always an implementation of a single common
module.
A regular module. Such modules target a specic platform and can either be dependencies of platform modules or depend
on platform modules.
A common module can depend only on other common modules and libraries, including the common version of the Kotlin
standard library ( kotlin-stdlib-common ). Common modules contain only Kotlin code, and not code in any other languages.
A platform module can depend on any modules and libraries available on the given platform (including Java libraries in case of
Kotlin/JVM and JS libraries for Kotlin/JS). Platform modules targeting Kotlin/JVM can also contain code in Java and other JVM
languages.
Compiling a common module produces a special metadata le containing all the declarations in the module. Compiling a
platform module produces target-specic code (JVM bytecode or JS source code) for the code in the platform module as well as
the common module that it implements.
Therefore, each multiplatform library needs to be distributed as a set of artifacts - a common .jar containing the metadata for
common code, as well as platform specic .jars containing the compiled implementation code for each platform.
To create a new multiplatform project in the IDE, select the "Kotlin (Multiplatform)" option under "Kotlin" in the New Project dialog.
This will create a project with three modules, a common one and two platform ones for JVM and JS. To add additional modules,
select one of the "Kotlin (Multiplatform)" options under "Gradle" in the New Module dialog.
If you need to congure the project manually, use the following steps:
Add the Kotlin Gradle plugin to the buildscript classpath: classpath "org.jetbrains.kotlin:kotlin-gradle-
plugin:$kotlin_version"
Add dependencies with implement scope from the platform modules to the common module
The following example demonstrates a complete build.gradle le for a common module with Kotlin 1.2-Beta:
135
buildscript {
ext.kotlin_version = '1.2-Beta'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.2' }
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.2' }
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
}
And the example below shows a complete build.gradle for a JVM module. Pay special attention to the implement line in the
dependencies block:
buildscript {
ext.kotlin_version = '1.2-Beta'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.2' }
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-eap-1.2' }
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implement project(":")
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
Platform-Speci c Declarations
One of the key capabilities of Kotlin's multiplatform code is a way for common code to depend on platform-specic declarations.
In other languages, this can often be accomplished by building a set of interfaces in the common code and implementing these
interfaces in platform-specic modules. However, this approach is not ideal in cases when you have a library on one of the
platforms that implements the functionality you need, and you'd like to use the API of this library directly without extra wrappers.
Also, it requires common declarations to be expressed as interfaces, which doesn't cover all possible cases.
136
As an alternative, Kotlin provides a mechanism of expected and actual declarations . With this mechanism, a common module
can dene expected declarations , and a platform module can provide actual declarations corresponding to the expected ones.
To see how this works, let's look at an example rst. This code is part of a common module:
package org.jetbrains.foo
package org.jetbrains.foo
An expected declaration in the common module and its actual counterparts always have exactly the same fully qualied
name.
An expected declaration is marked with the expect keyword; the actual declaration is marked with the actual keyword.
All actual declarations that match any part of an expected declaration need to be marked as actual .
Note that expected declarations are not restricted to interfaces and interface members. In this example, the expected class has
a constructor and can be created directly from common code. You can apply the expect modier to other declarations as well,
including top-level declarations and annotations:
// Common
expect fun formatString(source: String, vararg args: Any): String
// JVM
actual fun formatString(source: String, vararg args: Any) =
String.format(source, args)
The compiler ensures that every expected declaration has actual declarations in all platform modules that implement the
corresponding common module, and reports an error if any actual declarations are missing. The IDE provides tools that help you
create the missing actual declarations.
If you have a platform-specic library that you want to use in common code while providing your own implementation for another
platform, you can provide a typealias to an existing class as the actual declaration:
137
expect class AtomicRef<V>(value: V) {
fun get(): V
fun set(value: V)
fun getAndSet(value: V): V
fun compareAndSet(expect: V, update: V): Boolean
}
138
Reference
Keywords and Operators
Hard Keywords
The following tokens are always interpreted as keywords and cannot be used as identiers:
as
if begins an if expression
in
!in
is used as an operator to check that a value does NOT belong to a range, a collection or another entity that denes the
'contains' method
is used in when expressions for the same purpose
is
!is
checks that a value does NOT have a certain type
is used in when expressions for the same purpose
null is a constant representing an object reference that doesn't point to any object
139
return returns from the nearest enclosing function or anonymous function
super
this
refers to the current receiver
calls another constructor of the same class from a secondary constructor
Soft Keywords
The following tokens act as keywords in the context when they are applicable and can be used as identiers in other contexts:
by
delegates the implementation of an interface to another object
delegates the implementation of accessors for a property to another object
finally begins a block that is always executed when a try block exits
get
set
declares the setter of a property
is used as an annotation use-site target
Modi er Keywords
The following tokens act as keywords in modier lists of declarations and can be used as identiers in other contexts:
140
abstract marks a class or member as abstract
annotation declares an annotation class
external marks a declaration as implemented not in Kotlin (accessible through JNI or in JavaScript)
final forbids overriding a member
inner allows referring to the outer class instance from a nested class
internal marks a declaration as visible in the current module
protected marks a declaration as visible in the current class and its subclasses
tailrec marks a function as tail-recursive (allowing the compiler to replace recursion with iteration)
vararg allows passing a variable number of arguments for a parameter
field is used inside a property accessor to refer to the backing eld of the property
+ , - , * , / , % - mathematical operators
=
assignment operator
is used to specify default values for parameters
141
=== , !== - referential equality operators
< , > , <= , >= - comparison operators (translated to calls of compareTo() for non-primitive types)
?. performs a safe call (calls a method or accesses a property if the receiver is non-null)
?: takes the right-hand value if the left-hand value is null (the elvis operator)
.. creates a range
: separates a name from a type in declarations
@
introduces an annotation
introduces or references a loop label
introduces or references a lambda label
references a 'this' expression from an outer scope
references an outer superclass
_
substitutes an unused parameter in a lambda expression
substitutes an unused parameter in a destructuring declaration
142
Grammar
Notation
This section informally explains the grammar notation used below.
EBNF expressions
Operator | denotes alternative .
Operator * denotes iteration (zero or more).
Operator + denotes iteration (one or more).
Operator ? denotes option (zero or one).
alpha { beta } denotes a nonempty beta-separated list of alpha's.
Operator ``++'' means that no space or comment allowed between operands.
Semicolons
Kotlin provides "semicolon inference": syntactically, subsentences (e.g., statements, declarations etc) are separated by the
pseudo-token SEMI, which stands for "semicolon or newline". In most cases, there's no need for semicolons in Kotlin code.
Syntax
Relevant pages: Packages
start
kotlinFile
: preamble topLevelObject*
;
start
script
: preamble expression*
;
preamble
(used by script, kotlinFile)
: leAnnotations? packageHeader? import*
;
leAnnotations
(used by preamble)
: leAnnotation*
;
leAnnotation
(used by leAnnotations)
: "@" "le" ":" ("[" unescapedAnnotation+ "]" | unescapedAnnotation)
;
packageHeader
(used by preamble)
: modiers "package" SimpleName{"."} SEMI?
;
See Packages
import
(used by preamble)
: "import" SimpleName{"."} ("." "*" | "as" SimpleName)? SEMI?
;
See Imports
topLevelObject
(used by kotlinFile)
: class
: object
: function
: property
: typeAlias
;
typeAlias
(used by memberDeclaration, declaration, topLevelObject)
: modiers "typealias" SimpleName typeParameters? "=" type
143
;
Classes
See Classes and Inheritance
class
(used by memberDeclaration, declaration, topLevelObject)
: modiers ("class" | "interface") SimpleName
typeParameters?
primaryConstructor?
(":" annotations delegationSpecier{","})?
typeConstraints
(classBody? | enumClassBody)
;
primaryConstructor
(used by class, object)
: (modiers "constructor")? ("(" functionParameter{","} ")")
;
classBody
(used by objectLiteral, enumEntry, class, companionObject, object)
: ("{" members "}")?
;
members
(used by enumClassBody, classBody)
: memberDeclaration*
;
delegationSpecier
(used by objectLiteral, class, companionObject, object)
: constructorInvocation
: userType
: explicitDelegation
;
explicitDelegation
(used by delegationSpecier)
: userType "by" expression
;
typeParameters
(used by typeAlias, class, property, function)
: "<" typeParameter{","} ">"
;
typeParameter
(used by typeParameters)
: modiers SimpleName (":" userType)?
;
See Generic classes
typeConstraints
(used by class, property, function)
: ("where" typeConstraint{","})?
;
typeConstraint
(used by typeConstraints)
: annotations SimpleName ":" type
;
See Generic constraints
Class members
memberDeclaration
(used by members)
: companionObject
: object
: function
: property
: class
: typeAlias
: anonymousInitializer
: secondaryConstructor
;
anonymousInitializer
(used by memberDeclaration)
: "init" block
;
companionObject
(used by memberDeclaration)
: modiers "companion" "object" SimpleName? (":" delegationSpecier{","})? classBody?
;
valueParameters
(used by secondaryConstructor, function)
: "(" functionParameter{","}? ")"
;
functionParameter
(used by valueParameters, primaryConstructor)
: modiers ("val" | "var")? parameter ("=" expression)?
;
144
block
(used by catchBlock, anonymousInitializer, secondaryConstructor, functionBody, controlStructureBody, try, nallyBlock)
: "{" statements "}"
;
function
(used by memberDeclaration, declaration, topLevelObject)
: modiers "fun"
typeParameters?
(type ".")?
SimpleName
typeParameters? valueParameters (":" type)?
typeConstraints
functionBody?
;
functionBody
(used by getter, setter, function)
: block
: "=" expression
;
variableDeclarationEntry
(used by for, lambdaParameter, property, multipleVariableDeclarations)
: SimpleName (":" type)?
;
multipleVariableDeclarations
(used by for, lambdaParameter, property)
: "(" variableDeclarationEntry{","} ")"
;
property
(used by memberDeclaration, declaration, topLevelObject)
: modiers ("val" | "var")
typeParameters?
(type ".")?
(multipleVariableDeclarations | variableDeclarationEntry)
typeConstraints
("by" | "=" expression SEMI?)?
(getter? setter? | setter? getter?) SEMI?
;
See Properties and Fields
getter
(used by property)
: modiers "get"
: modiers "get" "(" ")" (":" type)? functionBody
;
setter
(used by property)
: modiers "set"
: modiers "set" "(" modiers (SimpleName | parameter) ")" functionBody
;
parameter
(used by functionType, setter, functionParameter)
: SimpleName ":" type
;
object
(used by memberDeclaration, declaration, topLevelObject)
: "object" SimpleName primaryConstructor? (":" delegationSpecier{","})? classBody?
secondaryConstructor
(used by memberDeclaration)
: modiers "constructor" valueParameters (":" constructorDelegationCall)? block
;
constructorDelegationCall
(used by secondaryConstructor)
: "this" valueArguments
: "super" valueArguments
;
See Object expressions and Declarations
Enum classes
enumClassBody
(used by class)
: "{" enumEntries (";" members)? "}"
;
enumEntries
(used by enumClassBody)
: (enumEntry{","} ","? ";"?)?
;
enumEntry
(used by enumEntries)
: modiers SimpleName ("(" arguments ")")? classBody?
;
Types
145
See Types
type
(used by namedInx, simpleUserType, getter, atomicExpression, whenCondition, property, typeArguments, function, typeAlias,
parameter, functionType, variableDeclarationEntry, lambdaParameter, typeConstraint)
: typeModiers typeReference
;
typeReference
(used by typeReference, nullableType, type)
: "(" typeReference ")"
: functionType
: userType
: nullableType
: "dynamic"
;
nullableType
(used by typeReference)
: typeReference "?"
;
userType
(used by typeParameter, catchBlock, callableReference, typeReference, delegationSpecier, constructorInvocation,
explicitDelegation)
: simpleUserType{"."}
;
simpleUserType
(used by userType)
: SimpleName ("<" (optionalProjection type | "*"){","} ">")?
;
optionalProjection
(used by simpleUserType)
: varianceAnnotation
;
functionType
(used by typeReference)
: (type ".")? "(" parameter{","}? ")" "->" type?
;
Control structures
See Control structures
controlStructureBody
(used by whenEntry, for, if, doWhile, while)
: block
: blockLevelExpression
;
if
(used by atomicExpression)
: "if" "(" expression ")" controlStructureBody SEMI? ("else" controlStructureBody)?
;
try
(used by atomicExpression)
: "try" block catchBlock* nallyBlock?
;
catchBlock
(used by try)
: "catch" "(" annotations SimpleName ":" userType ")" block
;
nallyBlock
(used by try)
: "nally" block
;
loop
(used by atomicExpression)
: for
: while
: doWhile
;
for
(used by loop)
: "for" "(" annotations (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" controlStructureBody
;
while
(used by loop)
: "while" "(" expression ")" controlStructureBody
;
doWhile
(used by loop)
: "do" controlStructureBody "while" "(" expression ")"
;
Expressions
Precedence
146
Precedence Title Symbols
Highest Postx ++, --, ., ?., ?
Prex -, +, ++, --, !, labelDefinition@
Type RHS :, as, as?
Multiplicative *, /, %
Additive +, -
Range ..
Inx function SimpleName
Elvis ?:
Named checks in, !in, is, !is
Comparison <, >, <=, >=
Equality ==, \!==
Conjunction &&
Disjunction ||
Lowest Assignment =, +=, -=, *=, /=, %=
Rules
expression
(used by for, atomicExpression, longTemplate, whenCondition, functionBody, doWhile, property, script, explicitDelegation, jump,
while, arrayAccess, blockLevelExpression, if, when, valueArguments, functionParameter)
: disjunction (assignmentOperator disjunction)*
;
disjunction
(used by expression)
: conjunction ("||" conjunction)*
;
conjunction
(used by disjunction)
: equalityComparison ("&&" equalityComparison)*
;
equalityComparison
(used by conjunction)
: comparison (equalityOperation comparison)*
;
comparison
(used by equalityComparison)
: namedInx (comparisonOperation namedInx)*
;
namedInx
(used by comparison)
: elvisExpression (inOperation elvisExpression)*
: elvisExpression (isOperation type)?
;
elvisExpression
(used by namedInx)
: inxFunctionCall ("?:" inxFunctionCall)*
;
inxFunctionCall
(used by elvisExpression)
: rangeExpression (SimpleName rangeExpression)*
;
rangeExpression
(used by inxFunctionCall)
: additiveExpression (".." additiveExpression)*
;
additiveExpression
(used by rangeExpression)
: multiplicativeExpression (additiveOperation multiplicativeExpression)*
;
multiplicativeExpression
(used by additiveExpression)
: typeRHS (multiplicativeOperation typeRHS)*
;
typeRHS
(used by multiplicativeExpression)
: prexUnaryExpression (typeOperation prexUnaryExpression)*
;
prexUnaryExpression
(used by typeRHS)
: prexUnaryOperation* postxUnaryExpression
;
postxUnaryExpression
(used by prexUnaryExpression, postxUnaryOperation)
: atomicExpression postxUnaryOperation*
: callableReference postxUnaryOperation*
147
;
callableReference
(used by postxUnaryExpression)
: (userType "?"*)? "::" SimpleName typeArguments?
;
atomicExpression
(used by postxUnaryExpression)
: "(" expression ")"
: literalConstant
: functionLiteral
: "this" labelReference?
: "super" ("<" type ">")? labelReference?
: if
: when
: try
: objectLiteral
: jump
: loop
: SimpleName
;
labelReference
(used by atomicExpression, jump)
: "@" ++ LabelName
;
labelDenition
(used by prexUnaryOperation, annotatedLambda)
: LabelName ++ "@"
;
literalConstant
(used by atomicExpression)
: "true" | "false"
: stringTemplate
: NoEscapeString
: IntegerLiteral
: HexadecimalLiteral
: CharacterLiteral
: FloatLiteral
: "null"
;
stringTemplate
(used by literalConstant)
: "\"" stringTemplateElement* "\""
;
stringTemplateElement
(used by stringTemplate)
: RegularStringPart
: ShortTemplateEntryStart (SimpleName | "this")
: EscapeSequence
: longTemplate
;
longTemplate
(used by stringTemplateElement)
: "${" expression "}"
;
declaration
(used by statement)
: function
: property
: class
: typeAlias
: object
;
statement
(used by statements)
: declaration
: blockLevelExpression
;
blockLevelExpression
(used by statement, controlStructureBody)
: annotations ("\n")+ expression
;
multiplicativeOperation
(used by multiplicativeExpression)
: "*" : "/" : "%"
;
additiveOperation
(used by additiveExpression)
: "+" : "-"
;
inOperation
(used by namedInx)
: "in" : "!in"
;
typeOperation
(used by typeRHS)
: "as" : "as?" : ":"
;
isOperation
(used by namedInx)
: "is" : "!is"
148
;
comparisonOperation
(used by comparison)
: "<" : ">" : ">=" : "<="
;
equalityOperation
(used by equalityComparison)
: "!=" : "=="
;
assignmentOperator
(used by expression)
: "="
: "+=" : "-=" : "*=" : "/=" : "%="
;
prexUnaryOperation
(used by prexUnaryExpression)
: "-" : "+"
: "++" : "--"
: "!"
: annotations
: labelDenition
;
postxUnaryOperation
(used by postxUnaryExpression)
: "++" : "--" : "!!"
: callSux
: arrayAccess
: memberAccessOperation postxUnaryExpression
;
callSux
(used by constructorInvocation, postxUnaryOperation)
: typeArguments? valueArguments annotatedLambda
: typeArguments annotatedLambda
;
annotatedLambda
(used by callSux)
: ("@" unescapedAnnotation)* labelDenition? functionLiteral
memberAccessOperation
(used by postxUnaryOperation)
: "." : "?." : "?"
;
typeArguments
(used by callSux, callableReference, unescapedAnnotation)
: "<" type{","} ">"
;
valueArguments
(used by callSux, constructorDelegationCall, unescapedAnnotation)
: "(" (SimpleName "=")? "*"? expression{","} ")"
;
jump
(used by atomicExpression)
: "throw" expression
: "return" ++ labelReference? expression?
: "continue" ++ labelReference?
: "break" ++ labelReference?
;
functionLiteral
(used by atomicExpression, annotatedLambda)
: "{" statements "}"
: "{" lambdaParameter{","} "->" statements "}"
;
lambdaParameter
(used by functionLiteral)
: variableDeclarationEntry
: multipleVariableDeclarations (":" type)?
;
statements
(used by block, functionLiteral)
: SEMI* statement{SEMI+} SEMI*
;
constructorInvocation
(used by delegationSpecier)
: userType callSux
;
arrayAccess
(used by postxUnaryOperation)
: "[" expression{","} "]"
;
objectLiteral
(used by atomicExpression)
: "object" (":" delegationSpecier{","})? classBody
;
When-expression
See When-expression
when
(used by atomicExpression)
149
: "when" ("(" expression ")")? "{"
whenEntry*
"}"
;
whenEntry
(used by when)
: whenCondition{","} "->" controlStructureBody SEMI
: "else" "->" controlStructureBody SEMI
;
whenCondition
(used by whenEntry)
: expression
: ("in" | "!in") expression
: ("is" | "!is") type
;
Modi ers
modiers
(used by typeParameter, getter, packageHeader, class, property, function, typeAlias, secondaryConstructor, enumEntry, setter,
companionObject, primaryConstructor, functionParameter)
: (modier | annotations)*
;
typeModiers
(used by type)
: (suspendModier | annotations)*
;
modier
(used by modiers)
: classModier
: accessModier
: varianceAnnotation
: memberModier
: parameterModier
: typeParameterModier
: functionModier
: propertyModier
;
classModier
(used by modier)
: "abstract"
: "nal"
: "enum"
: "open"
: "annotation"
: "sealed"
: "data"
;
memberModier
(used by modier)
: "override"
: "open"
: "nal"
: "abstract"
: "lateinit"
;
accessModier
(used by modier)
: "private"
: "protected"
: "public"
: "internal"
;
varianceAnnotation
(used by modier, optionalProjection)
: "in"
: "out"
;
parameterModier
(used by modier)
: "noinline"
: "crossinline"
: "vararg"
;
typeParameterModier
(used by modier)
: "reied"
;
functionModier
(used by modier)
: "tailrec"
: "operator"
: "inx"
: "inline"
: "external"
: suspendModier
;
propertyModier
(used by modier)
150
: "const"
;
suspendModier
(used by typeModiers, functionModier)
: "suspend"
;
Annotations
annotations
(used by catchBlock, prexUnaryOperation, blockLevelExpression, for, typeModiers, class, modiers, typeConstraint)
: (annotation | annotationList)*
;
annotation
(used by annotations)
: "@" (annotationUseSiteTarget ":")? unescapedAnnotation
;
annotationList
(used by annotations)
: "@" (annotationUseSiteTarget ":")? "[" unescapedAnnotation+ "]"
;
annotationUseSiteTarget
(used by annotation, annotationList)
: "eld"
: "le"
: "property"
: "get"
: "set"
: "receiver"
: "param"
: "setparam"
: "delegate"
;
unescapedAnnotation
(used by annotation, leAnnotation, annotatedLambda, annotationList)
: SimpleName{"."} typeArguments? valueArguments?
;
Lexical structure
helper
Digit
(used by IntegerLiteral, HexDigit)
: ["0".."9"];
IntegerLiteral
(used by literalConstant)
: Digit (Digit | "_")*
FloatLiteral
(used by literalConstant)
: <Java double literal>;
helper
HexDigit
(used by RegularStringPart, HexadecimalLiteral)
: Digit | ["A".."F", "a".."f"];
HexadecimalLiteral
(used by literalConstant)
: "0x" HexDigit (HexDigit | "_")*;
CharacterLiteral
(used by literalConstant)
: <character as in Java>;
See Basic types
NoEscapeString
(used by literalConstant)
: <"""-quoted string>;
RegularStringPart
(used by stringTemplateElement)
: <any character other than backslash, quote, $ or newline>
ShortTemplateEntryStart:
: "$"
EscapeSequence:
: UnicodeEscapeSequence | RegularEscapeSequence
UnicodeEscapeSequence:
: "\u" HexDigit{4}
RegularEscapeSequence:
: "\" <any character other than newline>
See String templates
SEMI
(used by whenEntry, if, statements, packageHeader, property, import)
: <semicolon or newline>;
SimpleName
(used by typeParameter, catchBlock, simpleUserType, atomicExpression, LabelName, packageHeader, class, object,
inxFunctionCall, function, typeAlias, parameter, callableReference, variableDeclarationEntry, stringTemplateElement, enumEntry,
setter, import, companionObject, valueArguments, unescapedAnnotation, typeConstraint)
: <java identier>
: "`" <java identier> "`"
;
151
See Java interoperability
LabelName
(used by labelReference, labelDenition)
: "@" SimpleName;
See Returns and jumps
152
Compatibility
This page describes compatibility guarantees for dierent versions and subsystems of Kotlin.
Compatibility glossary
Compatibility means answering the question: for given two versions of Kotlin (for example, 1.2 and 1.1.5), can the code written
for one version be used with another version? The list below explains the compatibility modes of dierent pairs of versions. Note
that a version is older if it has a smaller version number (even if it was released later than the version with a larger version
number). We use OV for "Older Version", and NV for "Newer Version".
C - Full Compatibility
Language
no syntax changes (modulo bugs *)
new warnings/hints may be added or removed
no API changes
deprecations with level WARNING may be added/removed
Binaries (ABI)
runtime: binaries can be used interchangeably
compilation: binaries can be used interchangeably
NO - No compatibility guarantees
we'll do our best to oer smooth migration, but can give no guarantees
migration is planned individually for every incompatible subsystem
* No changes modulo bugs means that if an important bug is found (e.g. in the compiler diagnostics or elsewhere), a x for it
may introduce a breaking change, but we are always very careful with such changes.
153
Compatibility guarantees for Kotlin releases
Kotlin for JVM:
Kotlin for JS: starting with Kotlin 1.1, both patch and minor version updates provide backward compatibility for the language
and API (BCLA), but no BCB.
Kotlin Scripts: both patch and minor version updates provide backward compatibility for the language and API (BCLA), but no
BCB.
Every platform may feature specic language extensions (such as platform types for JVM and dynamic types for JavaScript) or
restrictions (e.g. some overloading-related restrictions on the JVM), but the core language remains the same.
The Standard Library provides a core API available on all platforms, and we strive to make these APIs work in the same way on
every platform. Along with these, the Standard Library provides platform-specic extensions (e.g. java.io for JVM, or js() for
JavaScript), plus some APIs that can be called uniformly, but work dierently (such as regular expressions for JVM and JavaScript).
Experimental features
Experimental features, such as coroutines in Kotlin 1.1, have exemption from the compatibility modes listed above. Such
features require an opt-in to use without compiler warning. Experimental features are at least backwards compatible for patch
version updates, but we do not guarantee any compatibility for minor version updates (migration aids will be provided where
possible).
1.1.X BC - NO NO
1.2 NO NO - BC
1.2.X NO NO BC -
EAP builds
154
We publish Early Access Preview (EAP) builds to special channels where early adopters from the community can try them out
and give us feedback. Such builds provide no compatibility guarantees whatsoever (although we do our best to keep them
reasonably compatible with releases and with each other). Quality expectations for such builds are also much lower than for
releases. Beta builds also fall under this category.
IMPORTANT NOTE: all binaries compiled by EAP builds for 1.X (e.g. 1.1.0-eap-X) are rejected by release builds of the
compiler. We don't want any code compiled by pre-release versions to be kept around after a stable version is released. This
does not concern EAPs of patch versions (e.g. 1.1.3-eap-X), these EAPs produce builds with stable ABI.
Compatibility modes
When a big team is migrating onto a new version, it may appear in a "inconsistent state" at some point, when some developers
have already updated, and others haven't. To prevent the former from writing and committing code that others may not be able
to compile, we provide the following command line switches (also available in the IDE and Gradle/Maven):
-language-version X.Y - compatibility mode for Kotlin language version X.Y, reports errors for all language features that
came out later.
-api-version X.Y - compatibility mode for Kotlin API version X.Y, reports errors for all code using newer APIs from the Kotlin
Standard Library (including the code generated by the compiler).
For example, if OV = 1.0 and NV = 1.1, you can observe one of the following warnings:
Runtime JAR files in the classpath have the version 1.0, which is older than the API version 1.1.
Consider using the runtime of version 1.1, or pass '-api-version 1.0' explicitly to restrict the
available APIs to the runtime of version 1.0.
This means that you're using the Kotlin compiler 1.1 against the standard or reection library of version 1.0. This can be handled
in dierent ways:
If you intend to use the APIs from the 1.1 Standard Library, or language features that depend on those APIs, you should
upgrade the dependency to the version 1.1.
If you want to keep your code compatible with the 1.0 standard library, you can pass -api-version 1.0 .
If you've just upgraded to Kotlin 1.1 but can not use new language features yet (e.g. because some of your teammates may
not have upgraded), you can pass -language-version 1.0 , which will restrict all APIs and language features to 1.0.
Runtime JAR files in the classpath should have the same version. These files were found in the classpath:
kotlin-reflect.jar (version 1.0)
kotlin-stdlib.jar (version 1.1)
Consider providing an explicit dependency on kotlin-reflect 1.1 to prevent strange errors
Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the
classpath
This means that you have a dependency on libraries of dierent versions, for example the 1.1 standard library and the 1.0
reection library. To prevent subtle errors at runtime, we recommend you to use the same version of all Kotlin libraries. In this
case, consider adding an explicit dependency on the 1.1 reection library.
Some JAR files in the classpath have the Kotlin Runtime library bundled into them.
This may cause difficult to debug problems if there's a different version of the Kotlin Runtime library in the
classpath.
Consider removing these libraries from the classpath
This means that there's a library in the classpath which does not depend on the Kotlin standard library as a Gradle/Maven
dependency, but is distributed in the same artifact with it (i.e. has it bundled). Such a library may cause issues because standard
build tools do not consider it an instance of the Kotlin standard library, thus it's not subject to the dependency version resolution
mechanisms, and you can end up with several versions of the same library in the classpath. Consider contacting the authors of
such a library and suggesting to use the Gradle/Maven dependency instead.
155
Java Interop
Calling Java code from Kotlin
Kotlin is designed with Java Interoperability in mind. Existing Java code can be called from Kotlin in a natural way, and Kotlin code
can be used from Java rather smoothly as well. In this section we describe some details about calling Java code from Kotlin.
Pretty much all Java code can be used without any issues:
import java.util.*
For example:
import java.util.Calendar
fun calendarDemo() {
val calendar = Calendar.getInstance()
if (calendar.firstDayOfWeek == Calendar.SUNDAY) { // call getFirstDayOfWeek()
calendar.firstDayOfWeek = Calendar.MONDAY // call setFirstDayOfWeek()
}
if (!calendar.isLenient) { // call isLenient()
calendar.isLenient = true // call setLenient()
}
}
Note that, if the Java class only has a setter, it will not be visible as a property in Kotlin, because Kotlin does not support set-only
properties at this time.
156
Some of the Kotlin keywords are valid identiers in Java: in, object, is, etc. If a Java library uses a Kotlin keyword for a method,
you can still call the method escaping it with the backtick (`) character:
foo.`is`(bar)
When we call methods on variables of platform types, Kotlin does not issue nullability errors at compile time, but the call may fail
at runtime, because of a null-pointer exception or an assertion that Kotlin generates to prevent nulls from propagating:
Platform types are non-denotable , meaning that one can not write them down explicitly in the language. When a platform value is
assigned to a Kotlin variable, we can rely on type inference (the variable will have an inferred platform type then, as item has in
the example above), or we can choose the type that we expect (both nullable and non-null types are allowed):
If we choose a non-null type, the compiler will emit an assertion upon assignment. This prevents Kotlin's non-null variables from
holding nulls. Assertions are also emitted when we pass platform values to Kotlin functions expecting non-null values etc.
Overall, the compiler does its best to prevent nulls from propagating far through the program (although sometimes this is
impossible to eliminate entirely, because of generics).
As mentioned above, platform types cannot be mentioned explicitly in the program, so there's no syntax for them in the
language. Nevertheless, the compiler and IDE need to display them sometimes (in error messages, parameter info etc), so we
have a mnemonic notation for them:
Nullability annotations
Java types which have nullability annotations are represented not as platform types, but as actual nullable or non-null Kotlin
types. The compiler supports several avors of nullability annotations, including:
FindBugs ( edu.umd.cs.findbugs.annotations )
Eclipse ( org.eclipse.jdt.annotation )
Lombok ( lombok.NonNull ).
You can nd the full list in the Kotlin compiler source code.
157
JSR-305 Support
The @Nonnull annotation dened in JSR-305 is supported for denoting nullability of Java types.
If the @Nonnull(when = ...) value is When.ALWAYS , the annotated type is treated as non-null; When.MAYBE and When.NEVER
denote a nullable type; and When.UNKNOWN forces the type to be platform one.
A library can be compiled against the JSR-305 annotations, but there's no need to make the annotations artifact (e.g.
jsr305.jar ) a compile dependency for the library consumers. The Kotlin compiler can read the JSR-305 annotations from a
library without the annotations present on the classpath.
Since Kotlin 1.1.50, custom nullability qualiers (KEEP-79) are also supported (see below).
If an annotation type is annotated with both @TypeQualifierNickname and JSR-305 @Nonnull (or its another nickname, such as
@CheckForNull ), then the annotation type is itself used for retrieving precise nullability and has the same meaning as that
nullability annotation:
@TypeQualifierNickname
@Nonnull(when = When.ALWAYS)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyNonnull {
}
@TypeQualifierNickname
@CheckForNull // a nickname to another type qualifier nickname
@Retention(RetentionPolicy.RUNTIME)
public @interface MyNullable {
}
interface A {
@MyNullable String foo(@MyNonnull String x); // seen as `fun foo(x: String): String?`
String bar(List<@MyNonnull String> x); // seen as `fun bar(x: List<String>!): String!`
}
@TypeQualifierDefault allows introducing annotations that, when being applied, dene the default nullability within the scope
of the annotated element.
Such annotation type should itself be annotated with both @Nonnull (or its nickname) and @TypeQualifierDefault(...) with
one or more ElementType values:
The default nullability is used when a type itself is not annotated by a nullability annotation, and the default is determined by the
innermost enclosing element annotated with a type qualier default annotation with the ElementType matching the type usage.
158
@Nonnull
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
public @interface NonNullApi {
}
@Nonnull(when = When.MAYBE)
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE_USE})
public @interface NullableApi {
}
@NullableApi
interface A {
String foo(String x); // fun foo(x: String?): String?
// The type of `x` parameter remains platform because there's explicit UNKNOWN-marked
// nullability annotation:
String qux(@Nonnull(when = When.UNKNOWN) String x); // fun baz(x: String!): String?
}
// FILE: test/package-info.java
@NonNullApi // declaring all types in package 'test' as non-nullable by default
package test;
The @UnderMigration annotation (provided in a separate artifact kotlin-annotations-jvm ) can be used by library maintainers
to dene the migration status for the nullability type qualiers.
The status value in @UnderMigration(status = ...) species how the compiler treats inappropriate usages of the annotated
types in Kotlin (e.g. using a @MyNullable -annotated type value as non-null):
MigrationStatus.STRICT makes annotation work as any plain nullability annotation, i.e. reporting error for the inappropriate
usages;
with MigrationStatus.WARN , the inappropriate usages are reported as compilation warnings instead of errors; and
A library maintainer can add @UnderMigration status to both type qualier nicknames and type qualier defaults:
@Nonnull(when = When.ALWAYS)
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
@UnderMigration(status = MigrationStatus.WARN)
public @interface NonNullApi {
}
// The types in the class are non-null, but only warnings are reported
// because `@NonNullApi` is annotated `@UnderMigration(status = MigrationStatus.WARN)`
@NonNullApi
public class Test {}
Note: the migration status of a nullability annotation is not inherited by its type qualier nicknames but is applied to its usages in
default type qualiers.
159
If a default type qualier uses a type qualier nickname and they are both @UnderMigration , the status from the default type
qualier is used.
The JSR-305 checks can be congured by adding the -Xjsr305 compiler ag with the following options (and their
combination):
-Xjsr305={strict|warn|ignore} to set up the behavior for non- @UnderMigration annotations. Custom nullability
qualiers, especially @TypeQualifierDefault , are already spread among many well-known libraries, and users may need to
migrate smoothly when updating to the Kotlin version containing JSR-305 support. Since Kotlin 1.1.60, this ag only aects
non- @UnderMigration annotations.
-Xjsr305=@<fq.name>:{strict|warn|ignore} (since 1.1.60) to override the behavior for a single annotation, where
<fq.name> is the fully qualied class name of the annotation. May appear several times for dierent annotations. This is
useful for managing the migration state for a particular library.
The strict , warn and ignore values have the same meaning as those of MigrationStatus .
For kotlin versions 1.1.50+/1.2, the default behavior is the same to -Xjsr305=warn . The strict value should be considered
experimental (more checks may be added to it in the future).
Mapped types
Kotlin treats some Java types specially. Such types are not loaded from Java "as is", but are mapped to corresponding Kotlin
types. The mapping only matters at compile time, the runtime representation remains unchanged. Java's primitive types are
mapped to corresponding Kotlin types (keeping platform types in mind):
160
java.lang.Number
Java type kotlin.Number!
Kotlin type
java.lang.Throwable kotlin.Throwable!
Note that a boxed primitive type used as a type parameter is mapped to a platform type: for example,
List<java.lang.Integer> becomes a List<Int!> in Kotlin.
Collection types may be read-only or mutable in Kotlin, so Java's collections are mapped as follows (all Kotlin types in this table
reside in the package kotlin.collections ):
Java type Kotlin read-only type Kotlin mutable type Loaded platform type
Iterator<T> Iterator<T> MutableIterator<T> (Mutable)Iterator<T>!
Iterable<T> Iterable<T> MutableIterable<T> (Mutable)Iterable<T>!
Collection<T> Collection<T> MutableCollection<T> (Mutable)Collection<T>!
Set<T> Set<T> MutableSet<T> (Mutable)Set<T>!
List<T> List<T> MutableList<T> (Mutable)List<T>!
ListIterator<T> ListIterator<T> MutableListIterator<T> (Mutable)ListIterator<T>!
Map<K, V> Map<K, V> MutableMap<K, V> (Mutable)Map<K, V>!
Map.Entry<K, V> Map.Entry<K, V> MutableMap.MutableEntry<K,V> (Mutable)Map.(Mutable)Entry<K, V>!
Like Java's, Kotlin's generics are not retained at runtime, i.e. objects do not carry information about actual type arguments
passed to their constructors, i.e. ArrayList<Integer>() is indistinguishable from ArrayList<Character>() . This makes it
impossible to perform is-checks that take generics into account. Kotlin only allows is-checks for star-projected generic types:
161
Java Arrays
Arrays in Kotlin are invariant, unlike Java. This means that Kotlin does not let us assign an Array<String> to an Array<Any> ,
which prevents a possible runtime failure. Passing an array of a subclass as an array of superclass to a Kotlin method is also
prohibited, but for Java methods this is allowed (through platform types of the form Array<(out) String>! ).
Arrays are used with primitive datatypes on the Java platform to avoid the cost of boxing/unboxing operations. As Kotlin hides
those implementation details, a workaround is required to interface with Java code. There are specialized classes for every type
of primitive array ( IntArray , DoubleArray , CharArray , and so on) to handle this case. They are not related to the Array
class and are compiled down to Java's primitive arrays for maximum performance.
When compiling to JVM byte codes, the compiler optimizes access to arrays so that there's no overhead introduced:
Even when we navigate with an index, it does not introduce any overhead:
Java Varargs
Java classes sometimes use a method declaration for the indices with a variable number of arguments (varargs):
In that case you need to use the spread operator * to pass the IntArray :
162
val javaObj = JavaArrayExample()
val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndicesVarArg(*array)
It's currently not possible to pass null to a method that is declared as varargs.
Operators
Since Java has no way of marking methods for which it makes sense to use the operator syntax, Kotlin allows using any Java
methods with the right name and signature as operator overloads and other conventions ( invoke() etc.) Calling Java methods
using the inx call syntax is not allowed.
Checked Exceptions
In Kotlin, all exceptions are unchecked, meaning that the compiler does not force you to catch any of them. So, when you call a
Java method that declares a checked exception, Kotlin does not force you to do anything:
Object Methods
When Java types are imported into Kotlin, all the references of the type java.lang.Object are turned into Any . Since Any is
not platform-specic, it only declares toString() , hashCode() and equals() as its members, so to make other members of
java.lang.Object available, Kotlin uses extension functions.
wait()/notify()
Eective Java Item 69 kindly suggests to prefer concurrency utilities to wait() and notify() . Thus, these methods are not
available on references of type Any . If you really need to call them, you can cast to java.lang.Object :
(foo as java.lang.Object).wait()
getClass()
To retrieve the Java class of an object, use the java extension property on a class reference:
The code above uses a bound class reference, which is supported since Kotlin 1.1. You can also use the javaClass extension
property:
clone()
Do not forget about Eective Java, Item 11: Override clone judiciously.
163
nalize()
To override finalize() , all you need to do is simply declare it, without using the override keyword:
class C {
protected fun finalize() {
// finalization logic
}
}
if (Character.isLetter(a)) {
// ...
}
Java Re ection
Java reection works on Kotlin classes and vice versa. As mentioned above, you can use instance::class.java ,
ClassName::class.java or instance.javaClass to enter Java reection through java.lang.Class .
Other supported cases include acquiring a Java getter/setter method or a backing eld for a Kotlin property, a KProperty for a
Java eld, a Java method or constructor for a KFunction and vice versa.
SAM Conversions
Just like Java 8, Kotlin supports SAM conversions. This means that Kotlin function literals can be automatically converted into
implementations of Java interfaces with a single non-default method, as long as the parameter types of the interface method
match the parameter types of the Kotlin function.
If the Java class has multiple methods taking functional interfaces, you can choose the one you need to call by using an adapter
function that converts a lambda to a specic SAM type. Those adapter functions are also generated by the compiler when
needed:
Note that SAM conversions only work for interfaces, not for abstract classes, even if those also have just a single abstract
method.
Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions
into implementations of Kotlin interfaces is unnecessary and therefore unsupported.
164
Using JNI with Kotlin
To declare a function that is implemented in native (C or C++) code, you need to mark it with the external modier:
The rest of the procedure works in exactly the same way as in Java.
165
Calling Kotlin from Java
Kotlin code can be called from Java easily.
Properties
A Kotlin property is compiled to the following Java elements:
A getter method, with the name calculated by prepending the get prex;
A setter method, with the name calculated by prepending the set prex (only for var properties);
A private eld, with the same name as the property name (only for properties with backing elds).
For example, var firstName: String gets compiled to the following Java declarations:
If the name of the property starts with is , a dierent name mapping rule is used: the name of the getter will be the same as
the property name, and the name of the setter will be obtained by replacing is with set . For example, for a property isOpen ,
the getter will be called isOpen() and the setter will be called setOpen() . This rule applies for properties of any type, not just
Boolean .
Package-Level Functions
All the functions and properties declared in a le example.kt inside a package org.foo.bar , including extension functions,
are compiled into static methods of a Java class named org.foo.bar.ExampleKt .
// example.kt
package demo
class Foo
fun bar() {
}
// Java
new demo.Foo();
demo.ExampleKt.bar();
The name of the generated Java class can be changed using the @JvmName annotation:
@file:JvmName("DemoUtils")
package demo
class Foo
fun bar() {
}
166
// Java
new demo.Foo();
demo.DemoUtils.bar();
Having multiple les which have the same generated Java class name (the same package and the same name or the same
@JvmName annotation) is normally an error. However, the compiler has the ability to generate a single Java facade class which
has the specied name and contains all the declarations from all the les which have that name. To enable the generation of
such a facade, use the @JvmMultileClass annotation in all of the les.
// oldutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package demo
fun foo() {
}
// newutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package demo
fun bar() {
}
// Java
demo.Utils.foo();
demo.Utils.bar();
Instance Fields
If you need to expose a Kotlin property as a eld in Java, you need to annotate it with the @JvmField annotation. The eld will
have the same visibility as the underlying property. You can annotate a property with @JvmField if it has a backing eld, is not
private, does not have open , override or const modiers, and is not a delegated property.
// Java
class JavaClient {
public String getID(C c) {
return c.ID;
}
}
Late-Initialized properties are also exposed as elds. The visibility of the eld will be the same as the visibility of lateinit
property setter.
Static Fields
Kotlin properties declared in a named object or a companion object will have static backing elds either in that named object or
in the class containing the companion object.
Usually these elds are private but they can be exposed in one of the following ways:
@JvmField annotation;
167
lateinit modier;
const modier.
Annotating such a property with @JvmField makes it a static eld with the same visibility as the property itself.
// Java
Key.COMPARATOR.compare(key1, key2);
// public static final field in Key class
A late-initialized property in an object or a companion object has a static backing eld with the same visibility as the property
setter.
object Singleton {
lateinit var provider: Provider
}
// Java
Singleton.provider = new Provider();
// public static non-final field in Singleton class
Properties annotated with const (in classes as well as at the top level) are turned into static elds in Java:
// file example.kt
object Obj {
const val CONST = 1
}
class C {
companion object {
const val VERSION = 9
}
}
In Java:
int c = Obj.CONST;
int d = ExampleKt.MAX;
int v = C.VERSION;
Static Methods
As mentioned above, Kotlin represents package-level functions as static methods. Kotlin can also generate static methods for
functions dened in named objects or companion objects if you annotate those functions as @JvmStatic . If you use this
annotation, the compiler will generate both a static method in the enclosing class of the object and an instance method in the
object itself. For example:
168
class C {
companion object {
@JvmStatic fun foo() {}
fun bar() {}
}
}
object Obj {
@JvmStatic fun foo() {}
fun bar() {}
}
In Java:
@JvmStatic annotation can also be applied on a property of an object or a companion object making its getter and setter
methods be static members in that object or the class containing the companion object.
Visibility
The Kotlin visibilities are mapped to Java in the following way:
KClass
Sometimes you need to call a Kotlin method with a parameter of type KClass . There is no automatic conversion from Class to
KClass , so you have to do it manually by invoking the equivalent of the Class<T>.kotlin extension property:
kotlin.jvm.JvmClassMappingKt.getKotlinClass(MainView.class)
169
fun List<String>.filterValid(): List<String>
fun List<Int>.filterValid(): List<Int>
These two functions can not be dened side-by-side, because their JVM signatures are the same:
filterValid(Ljava/util/List;)Ljava/util/List; . If we really want them to have the same name in Kotlin, we can annotate
one (or both) of them with @JvmName and specify a dierent name as an argument:
@JvmName("filterValidInt")
fun List<Int>.filterValid(): List<Int>
From Kotlin they will be accessible by the same name filterValid , but from Java it will be filterValid and filterValidInt .
The same trick applies when we need to have a property x alongside with a function getX() :
val x: Int
@JvmName("getX_prop")
get() = 15
fun getX() = 10
Overloads Generation
Normally, if you write a Kotlin function with default parameter values, it will be visible in Java only as a full signature, with all
parameters present. If you wish to expose multiple overloads to Java callers, you can use the @JvmOverloads annotation.
The annotation also works for constructors, static methods etc. It can't be used on abstract methods, including methods
dened in interfaces.
For every parameter with a default value, this will generate one additional overload, which has this parameter and all parameters
to the right of it in the parameter list removed. In this example, the following will be generated:
// Constructors:
Foo(int x, double y)
Foo(int x)
// Methods
void f(String a, int b, String c) { }
void f(String a, int b) { }
void f(String a) { }
Note that, as described in Secondary Constructors, if a class has default values for all constructor parameters, a public no-
argument constructor will be generated for it. This works even if the @JvmOverloads annotation is not specied.
Checked Exceptions
As we mentioned above, Kotlin does not have checked exceptions. So, normally, the Java signatures of Kotlin functions do not
declare exceptions thrown. Thus if we have a function in Kotlin like this:
170
// example.kt
package demo
fun foo() {
throw IOException()
}
// Java
try {
demo.Example.foo();
}
catch (IOException e) { // error: foo() does not declare IOException in the throws list
// ...
}
we get an error message from the Java compiler, because foo() does not declare IOException . To work around this problem,
use the @Throws annotation in Kotlin:
@Throws(IOException::class)
fun foo() {
throw IOException()
}
Null-safety
When calling Kotlin functions from Java, nobody prevents us from passing null as a non-null parameter. That's why Kotlin
generates runtime checks for all public functions that expect non-nulls. This way we get a NullPointerException in the Java
code immediately.
Variant generics
When Kotlin classes make use of declaration-site variance, there are two options of how their usages are seen from the Java
code. Let's say we have the following class and two functions that use it:
interface Base
class Derived : Base
The problem is that in Kotlin we can say unboxBase(boxDerived("s")) , but in Java that would be impossible, because in Java
the class Box is invariant in its parameter T , and thus Box<Derived> is not a subtype of Box<Base> . To make it work in Java
we'd have to dene unboxBase as follows:
Here we make use of Java's wildcards types ( ? extends Base ) to emulate declaration-site variance through use-site variance,
because it is all Java has.
171
To make Kotlin APIs work in Java we generate Box<Super> as Box<? extends Super> for covariantly dened Box (or Foo<?
super Bar> for contravariantly dened Foo ) when it appears as a parameter. When it's a return value, we don't generate
wildcards, because otherwise Java clients will have to deal with them (and it's against the common Java coding style). Therefore,
the functions from our example are actually translated as follows:
// parameter - wildcards
Base unboxBase(Box<? extends Base> box) { ... }
NOTE: when the argument type is nal, there's usually no point in generating the wildcard, so Box<String> is always
Box<String> , no matter what position it takes.
If we need wildcards where they are not generated by default, we can use the @JvmWildcard annotation:
On the other hand, if we don't need wildcards where they are generated, we can use @JvmSuppressWildcards :
NOTE: @JvmSuppressWildcards can be used not only on individual type arguments, but on entire declarations, such as
functions or classes, causing all wildcards inside them to be suppressed.
The type Nothing is special, because it has no natural counterpart in Java. Indeed, every Java reference type, including
java.lang.Void , accepts null as a value, and Nothing doesn't accept even that. So, this type cannot be accurately
represented in the Java world. This is why Kotlin generates a raw type where an argument of type Nothing is used:
172
JavaScript
Dynamic Type
Being a statically typed language, Kotlin still has to interoperate with untyped or loosely typed environments, such as the
JavaScript ecosystem. To facilitate these use cases, the dynamic type is available in the language:
a value of this type can be assigned to any variable or passed anywhere as a parameter;
any value can be assigned to a variable of type dynamic or passed to a function that takes dynamic as a parameter;
The most peculiar feature of dynamic is that we are allowed to call any property or function with any parameters on a dynamic
variable:
On the JavaScript platform this code will be compiled "as is": dyn.whatever(1) in Kotlin becomes dyn.whatever(1) in the
generated JavaScript code.
When calling functions written in Kotlin on values of dynamic type, keep in mind the name mangling performed by the Kotlin to
JavaScript compiler. You may need to use the @JsName annotation to assign well-dened names to the functions that you need
to call.
A dynamic call always returns dynamic as a result, so we can chain such calls freely:
dyn.foo().bar.baz()
When we pass a lambda to a dynamic call, all of its parameters by default have the type dynamic :
dyn.foo {
x -> x.bar() // x is dynamic
}
Expressions using values of dynamic type are translated to JavaScript "as is", and do not use the Kotlin operator conventions.
The following operators are supported:
assignments: += , -= , *= , /= , %=
indexed access:
173
read: d[a] , more than one argument is an error
174
Calling JavaScript from Kotlin
Kotlin was designed for easy interoperation with Java platform. It sees Java classes as Kotlin classes, and Java sees Kotlin classes
as Java classes. However, JavaScript is a dynamically-typed language, which means it does not check types in compile-time. You
can freely talk to JavaScript from Kotlin via dynamic types, but if you want the full power of Kotlin type system, you can create
Kotlin headers for JavaScript libraries.
Inline JavaScript
You can inline some JavaScript code into your Kotlin code using the js("") function. For example:
The parameter of js is required to be a string constant. So, the following code is incorrect:
external modi er
To tell Kotlin that a certain declaration is written in pure JavaScript, you should mark it with external modier. When the compiler
sees such a declaration, it assumes that the implementation for the corresponding class, function or property is provided by the
developer, and therefore does not try to generate any JavaScript code from the declaration. This means that you should omit
bodies of external declarations. For example:
// etc
}
Note that external modier is inherited by nested declarations, i.e. in Node class we do not put external before member
functions and properties.
The external modier is only allowed on package-level declarations. You can't declare an external member of a
non- external class.
In JavaScript you can dene members either on a prototype or a class itself. I.e.:
function MyClass() {
}
MyClass.sharedMember = function() { /* implementation */ };
MyClass.prototype.ownMember = function() { /* implementation */ };
There's no such syntax in Kotlin. However, in Kotlin we have companion objects. Kotlin treats companion objects of external
class in a special way: instead of expecting an object, it assumes members of companion objects to be members of the class
itself. To describe MyClass from the example above, you can write:
175
external class MyClass {
companion object {
fun sharedMember()
}
fun ownMember()
}
An external function can have optional parameters. How the JavaScript implementation actually computes default values for
these parameters, is unknown to Kotlin, thus it's impossible to use the usual syntax to declare such parameters in Kotlin. You
should use the following syntax:
This means you can call myFunWithOptionalArgs with one required argument and two optional arguments (their default values
are calculated by some JavaScript code).
You can easily extend JavaScript classes as they were Kotlin classes. Just dene an external class and extend it by
non- external class. For example:
1. When a function of external base class is overloaded by signature, you can't override it in a derived class.
2. You can't override a function with default arguments.
external interfaces
JavaScript does not have the concept of interfaces. When a function expects its parameter to support foo and bar methods,
you just pass objects that actually have these methods. You can use interfaces to express this for statically-typed Kotlin, for
example:
fun bar()
}
Another use case for external interfaces is to describe settings objects. For example:
176
external interface JQueryAjaxSettings {
var async: Boolean
// etc
}
fun sendQuery() {
JQuery.get(JQueryAjaxSettings().apply {
complete = { (xhr, data) ->
window.alert("Request complete")
}
})
}
177
Calling Kotlin from JavaScript
Kotlin compiler generates normal JavaScript classes, functions and properties you can freely use from JavaScript code.
Nevertheless, there are some subtle things you should remember.
alert(myModule.foo());
This is not applicable when you compile your Kotlin module to JavaScript module (see JavaScript Modules for more information on
this). In this case there won't be a wrapper object, instead, declarations will be exposed as a JavaScript module of a
corresponding kind. For example, in case of CommonJS you should write:
alert(require('myModule').foo());
Package structure
Kotlin exposes its package structure to JavaScript, so unless you dene your declarations in the root package, you have to use
fully-qualied names in JavaScript. For example:
package my.qualified.packagename
alert(myModule.my.qualified.packagename.foo());
@JsName annotation
In some cases (for example, to support overloads), Kotlin compiler mangles names of generated functions and attributes in
JavaScript code. To control the generated names, you can use the @JsName annotation:
// Module 'kjs'
class Person(val name: String) {
fun hello() {
println("Hello $name!")
}
@JsName("helloWithGreeting")
fun hello(greeting: String) {
println("$greeting $name!")
}
}
Now you can use this class from JavaScript in the following way:
178
If we didn't specify the @JsName annotation, the name of the corresponding function would contain a sux calculated from the
function signature, for example hello_61zpoe$ .
Note that Kotlin compiler does not apply such mangling to external declarations, so you don't have to use @JsName on them.
Another case worth noticing is inheriting non-external classes from external classes. In this case any overridden functions won't
be mangled as well.
The parameter of @JsName is required to be a constant string literal which is a valid identier. The compiler will report an error on
any attempt to pass non-identier string to @JsName . The following example produces a compile-time error:
fun f() {
val x: Int = 23
val y: Any = x
println(y as Float)
}
Kotlin preserves overow semantics for kotlin.Int , kotlin.Byte , kotlin.Short , kotlin.Char and kotlin.Long .
There's no 64 bit integer number in JavaScript, so kotlin.Long is not mapped to any JavaScript object, it's emulated by a
Kotlin class.
kotlin.String is mapped to JavaScript String.
kotlin.Any is mapped to JavaScript Object (i.e. new Object() , {} , etc).
Kotlin collections (i.e. List , Set , Map , etc) are not mapped to any specic JavaScript type.
kotlin.Throwable is mapped to JavaScript Error.
Starting with version 1.1.50 primitive array translation utilizes JavaScript TypedArray:
kotlin.ByteArray , -.ShortArray , -.IntArray , -.FloatArray , and -.DoubleArray are mapped to JavaScript Int8Array,
Int16Array, Int32Array, Float32Array, and Float64Array correspondingly.
kotlin.BooleanArray is mapped to JavaScript Int8Array with a property $type$ == "BooleanArray"
kotlin.CharArray is mapped to JavaScript UInt16Array with a property $type$ == "CharArray"
179
JavaScript Modules
Kotlin allows you to compile your Kotlin projects to JavaScript modules for popular module systems. Here is the list of available
options:
1. Plain. Don't compile for any module system. As usual, you can access a module by its name in the global scope. This option
is used by default.
2. Asynchronous Module Denition (AMD), which is in particular used by require.js library.
3. CommonJS convention, widely used by node.js/npm ( require function and module.exports object)
4. Unied Module Denitions (UMD), which is compatible with both AMD and CommonJS, and works as "plain" when neither
AMD nor CommonJS is available at runtime.
Setup per module: Open File -> Project Structure, nd your module in Modules and select "Kotlin" facet under it. Choose
appropriate module system in "Module kind" eld.
Setup for the whole project: Open File -> Settings, select "Build, Execution, Deployment" -> "Compiler" -> "Kotlin compiler".
Choose appropriate module system in "Module kind" eld.
From Maven
To select module system when compiling via Maven, you should set moduleKind conguration property, i.e. your pom.xml
should look like this:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>js</goal>
</goals>
</execution>
</executions>
<!-- Insert these lines -->
<configuration>
<moduleKind>commonjs</moduleKind>
</configuration>
<!-- end of inserted text -->
</plugin>
From Gradle
To select module system when compiling via Gradle, you should set moduleKind property, i.e.
compileKotlin2Js.kotlinOptions.moduleKind = "commonjs"
@JsModule annotation
To tell Kotlin that an external class, package, function or property is a JavaScript module, you can use @JsModule annotation.
Consider you have the following CommonJS module called "hello":
180
module.exports.sayHello = function(name) { alert("Hello, " + name); }
@JsModule("hello")
external fun sayHello(name: String)
Some JavaScript libraries export packages (namespaces) instead of functions and classes. In terms of JavaScript is's an object
that has members that are classes, functions and properties. Importing these packages as Kotlin objects often looks unnatural.
The compiler allows to map imported JavaScript packages to Kotlin packages, using the following notation:
@file:JsModule("extModule")
package ext.jspackage.name
external class C
module.exports = {
foo: { /* some code here */ },
C: { /* some code here */ }
}
Important: les marked with @file:JsModule annotation can't declare non-external members. The example below produces
compile-time error:
@file:JsModule("extModule")
package ext.jspackage.name
In the previous example the JavaScript module exports a single package. However, some JavaScript libraries export multiple
packages from within a module. This case is also supported by Kotlin, though you have to declare a new .kt le for each
package you import.
module.exports = {
mylib: {
pkg1: {
foo: function() { /* some code here */ },
bar: function() { /* some code here */ }
},
pkg2: {
baz: function() { /* some code here */ }
}
}
}
To import this module in Kotlin, you have to write two Kotlin source les:
181
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg1")
package extlib.pkg1
and
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg2")
package extlib.pkg2
@JsNonModule annotation
When a declaration has @JsModule , you can't use it from Kotlin code when you don't compile it to a JavaScript module. Usually,
developers distribute their libraries both as JavaScript modules and downloadable .js les that you can copy to project's static
resources and include via <script> element. To tell Kotlin that it's ok to use a @JsModule declaration from non-module
environment, you should put @JsNonModule declaration. For example, given JavaScript code:
@JsModule("hello")
@JsNonModule
@JsName("topLevelSayHello")
external fun sayHello(name: String)
Notes
Kotlin is distributed with kotlin.js standard library as a single le, which is itself compiled as an UMD module, so you can use it
with any module system described above. Also it is available on NPM as kotlin package
182
JavaScript Re ection
At this time, JavaScript does not support the full Kotlin reection API. The only supported part of the API is the ::class syntax
which allows you to refer to the class of an instance, or the class corresponding to the given type. The value of a ::class
expression is a stripped-down KClass implementation that only supports the simpleName and isInstance members.
In addition to that, you can use KClass.js to access the JsClass instance corresponding to the class. The JsClass instance itself
is a reference to the constructor function. This can be used to interoperate with JS functions that expect a reference to a
constructor.
Examples:
class A
class B
class C
val a = A()
println(a::class.simpleName) // Obtains class for an instance; prints "A"
println(B::class.simpleName) // Obtains class for a type; prints "B"
println(B::class.js.name) // prints "B"
foo<C>() // prints "C"
183
JavaScript DCE
Since version 1.1.4, Kotlin/JS includes a dead code elimination (DCE) tool. This tool allows to strip out unused properties,
functions and classes from the generated JS. There are several ways you get unused declarations:
Functions can be inlined and never get called directly (which happens always except for few situations).
You are using a shared library which provides much more functions than you actually need. For example, standard library
( kotlin.js ) contains functions for manipulating lists, arrays, char sequences, adapters for DOM, etc, which together gives
about 1.3 mb le. A simple "Hello, world" application only requires console routines, which is only few kilobytes for the entire
le.
How to use
DCE tool is currently available from Gradle.
Note that if you are using multi-project build, you should apply plugin to the main project that is an entry point to your application.
By default, the resulting set of JavaScript les (your application together with all dependencies) can be found at path
$BUILD_DIR/min/ , where $BUILD_DIR is the path to generated JavaScript (usually, build/classes/main ).
Con guring
To congure DCE on the main source set, you can use the runDceKotlinJs task (and corresponding
runDce<sourceSetName>KotlinJs for other source sets).
Sometimes you are going to use a Kotlin declaration directly from JavaScript, and it's being stripped out by DCE. You may want to
keep this declaration. To do so, you can use the following syntax in build.gradle :
moduleName.dot.separated.package.name.declarationName
For example, consider a module is named kotlin-js-example and it contains a function named toKeep in package
org.jetbrains.kotlin.examples . Use the following line:
runDceKotlinJs.keep "kotlin-js-example_main.org.jetbrains.kotlin.examples.toKeep"
Note that if your function has parameters, its name will be mangled, so the mangled name should be used in the keep directive.
Example
A full example that shows how to integrate Kotlin with DCE and webpack to get a small bundle, can be found here.
Notes
As for 1.1.x versions, DCE tool is an experimental feature. This does not mean we are going to remove it, or that it's
unusable for production. This means that we can change names of conguration parameters, default settings, etc.
Currently you should not use DCE tool if your project is a shared library. It's only applicable when you are developing an
application (which may use shared libraries). The reason is: DCE does not know which parts of the library are going to be
used by the user's application.
DCE does not perform minication (uglication) of your code by removing unnecessary whitespaces and shortening
identiers. You should use existing tools, like UglifyJS (https://github.com/mishoo/UglifyJS2) or Google Closure Compiler
(https://developers.google.com/closure/compiler/) for this purpose.
184
Tools
Documenting Kotlin Code
The language used to document Kotlin code (the equivalent of Java's JavaDoc) is called KDoc. In its essence, KDoc combines
JavaDoc's syntax for block tags (extended to support Kotlin's specic constructs) and Markdown for inline markup.
Dokka has plugins for Gradle, Maven and Ant, so you can integrate documentation generation into your build process.
KDoc Syntax
Just like with JavaDoc, KDoc comments start with /** and end with */ . Every line of the comment may begin with an asterisk,
which is not considered part of the contents of the comment.
By convention, the rst paragraph of the documentation text (the block of text until the rst blank line) is the summary
description of the element, and the following text is the detailed description.
Every block tag begins on a new line and starts with the @ character.
/**
* A group of *members*.
*
* This class has no useful logic; it's just a documentation example.
*
* @param T the type of a member in this group.
* @property name the name of this group.
* @constructor Creates an empty group.
*/
class Group<T>(val name: String) {
/**
* Adds a [member] to this group.
* @return the new size of the group.
*/
fun add(member: T): Int { ... }
}
Block Tags
KDoc currently supports the following block tags:
@param <name>
Documents a value parameter of a function or a type parameter of a class, property or function. To better separate the
parameter name from the description, if you prefer, you can enclose the name of the parameter in brackets. The following two
syntaxes are therefore equivalent:
185
@return
@constructor
@receiver
@property <name>
Documents the property of a class which has the specied name. This tag can be used for documenting properties declared in
the primary constructor, where putting a doc comment directly before the property denition would be awkward.
Documents an exception which can be thrown by a method. Since Kotlin does not have checked exceptions, there is also no
expectation that all possible exceptions are documented, but you can still use this tag when it provides useful information for
users of the class.
@sample <identifier>
Embeds the body of the function with the specied qualied name into the documentation for the current element, in order to
show an example of how the element could be used.
@see <identifier>
Adds a link to the specied class or method to the See Also block of the documentation.
@author
@since
Species the version of the software in which the element being documented was introduced.
@suppress
Excludes the element from the generated documentation. Can be used for elements which are not part of the ocial API of a
module but still have to be visible externally.
KDoc does not support the @deprecated tag. Instead, please use the @Deprecated annotation.
Inline Markup
For inline markup, KDoc uses the regular Markdown syntax, extended to support a shorthand syntax for linking to other
elements in the code.
Linking to Elements
To link to another element (class, method, property or parameter), simply put its name in square brackets:
If you want to specify a custom label for the link, use the Markdown reference-style syntax:
186
You can also use qualied names in the links. Note that, unlike JavaDoc, qualied names always use the dot character to
separate the components, even before a method name:
Names in links are resolved using the same rules as if the name was used inside the element being documented. In particular,
this means that if you have imported a name into the current le, you don't need to fully qualify it when you use it in a KDoc
comment.
Note that KDoc does not have any syntax for resolving overloaded members in links. Since the Kotlin documentation generation
tool puts the documentation for all overloads of a function on the same page, identifying a specic overloaded function is not
required for the link to work.
Inside the le, the documentation for the module as a whole and for individual packages is introduced by the corresponding
rst-level headings. The text of the heading must be "Module <module name> " for the module, and "Package <package
qualified name> " for a package.
# Module kotlin-demo
# Package org.jetbrains.kotlin.demo
## Level 2 heading
# Package org.jetbrains.kotlin.demo2
187
Annotation processing with Kotlin
Annotation processors (see JSR 269) are supported in Kotlin with the kapt compiler plugin.
Being short, you can use libraries such as Dagger or Data Binding in your Kotlin projects.
Please read below about how to apply the kapt plugin to your Gradle/Maven build.
Using in Gradle
Apply the kotlin-kapt Gradle plugin:
plugins {
id "org.jetbrains.kotlin.kapt" version "1.1.60"
}
Then add the respective dependencies using the kapt conguration in your dependencies block:
dependencies {
kapt 'groupId:artifactId:version'
}
If you previously used the Android support for annotation processors, replace usages of the annotationProcessor
conguration with kapt . If your project contains Java classes, kapt will also take care of them.
If you use annotation processors for your androidTest or test sources, the respective kapt congurations are named
kaptAndroidTest and kaptTest . Note that kaptAndroidTest and kaptTest extends kapt , so you can just provide the
kapt dependency and it will be available both for production sources and tests.
Some annotation processors (such as AutoFactory ) rely on precise types in declaration signatures. By default, Kapt replaces
every unknown type (including types for the generated classes) to NonExistentClass , but you can change this behavior. Add
the additional ag to the build.gradle le to enable error type inferring in stubs:
kapt {
correctErrorTypes = true
}
Using in Maven
Add an execution of the kapt goal from kotlin-maven-plugin before compile :
188
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<!-- Specify your annotation processors here. -->
<annotationProcessorPath>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>2.9</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
You can nd a complete sample project showing the use of Kotlin, Maven and Dagger in the Kotlin examples repository.
Please note that kapt is still not supported for IntelliJ IDEAs own build system. Launch the build from the Maven Projects
toolbar whenever you want to re-run the annotation processing.
Using in CLI
Kapt compiler plugin is available in the binary distribution of the Kotlin compiler.
You can attach the plugin by providing the path to its JAR le using the Xplugin kotlinc option:
-Xplugin=$KOTLIN_HOME/lib/kotlin-annotation-processing.jar
classes (required): An output path for the generated class les and resources.
stubs (required): An output path for the stub les. In other words, some temporary directory.
apclasspath (repeatable ): A path to the annotation processor JAR. Pass as many apclasspath options as many JARs you
have.
apoptions : A base64-encoded list of the annotation processor options. See AP/javac options encoding for more
information.
javacArguments : A base64-encoded list of the options passed to javac. See AP/javac options encoding for more
information.
processors : A comma-specied list of annotation processor qualied class names. If specied, kapt does not try to nd
annotation processors in apclasspath .
verbose : Enable verbose output.
aptMode (required)
The plugin option format is: -P plugin:<plugin id>:<key>=<value> . Options can be repeated.
An example:
189
-P plugin:org.jetbrains.kotlin.kapt3:sources=build/kapt/sources
-P plugin:org.jetbrains.kotlin.kapt3:classes=build/kapt/classes
-P plugin:org.jetbrains.kotlin.kapt3:stubs=build/kapt/stubs
-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/ap.jar
-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=lib/anotherAp.jar
-P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true
Note that Kapt does not support multiple rounds for the generated Kotlin les.
oos.writeInt(options.size)
for ((key, value) in options.entries) {
oos.writeUTF(key)
oos.writeUTF(value)
}
oos.flush()
return Base64.getEncoder().encodeToString(os.toByteArray())
}
190
Using Gradle
In order to build Kotlin with Gradle you should set up the kotlin-gradle plugin, apply it to your project and add kotlin-stdlib
dependencies. Those actions may also be performed automatically in IntelliJ IDEA by invoking the Tools | Kotlin | Congure Kotlin
in Project action.
buildscript {
ext.kotlin_version = '1.1.60'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
This is not required when using Kotlin Gradle plugin 1.1.1 and above with the Gradle plugins DSL.
Or, starting with Kotlin 1.1.1, the plugin can be applied using the Gradle plugins DSL:
plugins {
id "org.jetbrains.kotlin.jvm" version "1.1.60"
}
The version should be literal in this block, and it cannot be applied from another build script.
Kotlin sources can be mixed with Java sources in the same folder, or in dierent folders. The default convention is using dierent
folders:
project
- src
- main (root)
- kotlin
- java
The corresponding sourceSets property should be updated if not using the default convention:
sourceSets {
main.kotlin.srcDirs += 'src/main/myKotlin'
main.java.srcDirs += 'src/main/myJava'
}
Targeting JavaScript
When targeting JavaScript, a dierent plugin should be applied:
191
apply plugin: "kotlin2js"
This plugin only works for Kotlin les so it is recommended to keep Kotlin and Java les separate (if it's the case that the same
project contains Java les). As with targeting the JVM, if not using the default convention, we need to specify the source folder
using sourceSets :
sourceSets {
main.kotlin.srcDirs += 'src/main/myKotlin'
}
In addition to the output JavaScript le, the plugin by default creates an additional JS le with binary descriptors. This le is
required if you're building a re-usable library that other Kotlin modules can depend on, and should be distributed together with
the result of translation. The generation is controlled by the kotlinOptions.metaInfo option:
compileKotlin2Js {
kotlinOptions.metaInfo = true
}
Targeting Android
Android's Gradle model is a little dierent from ordinary Gradle, so if we want to build an Android project written in Kotlin, we
need kotlin-android plugin instead of kotlin:
buildscript {
ext.kotlin_version = '1.1.60'
...
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
Android Studio
android {
...
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
This lets Android Studio know that the kotlin directory is a source root, so when the project model is loaded into the IDE it will be
properly recognized. Alternatively, you can put Kotlin classes in the Java source directory, typically located in src/main/java .
192
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib"
}
If you're targeting JDK 7 or JDK 8, you can use extended versions of the Kotlin standard library which contain additional extension
functions for APIs added in new JDK versions. Instead of kotlin-stdlib , use one of the following dependencies:
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
If your project uses Kotlin reection or testing facilities, you need to add the corresponding dependencies as well:
compile "org.jetbrains.kotlin:kotlin-reflect"
testCompile "org.jetbrains.kotlin:kotlin-test"
testCompile "org.jetbrains.kotlin:kotlin-test-junit"
Starting with Kotlin 1.1.2, the dependencies with group org.jetbrains.kotlin are by default resolved with the version taken
from the applied plugin. You can provide the version manually using the full dependency notation like compile
"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" .
Annotation processing
See the description of Kotlin annotation processing tool ( kapt ).
Incremental compilation
Kotlin supports optional incremental compilation in Gradle. Incremental compilation tracks changes of source les between
builds so only les aected by these changes would be compiled.
2. add -Pkotlin.incremental=true or -Pkotlin.incremental=false to gradle command line parameters. Note that in this
case the parameter should be added to each subsequent build, and any build with disabled incremental compilation
invalidates incremental caches.
When incremental compilation is enabled, you should see the following warning message in your build log:
Coroutines support
Coroutines support is an experimental feature in Kotlin 1.1, so the Kotlin compiler reports a warning when you use coroutines in
your project. To turn o the warning, add the following block to your build.gradle le:
kotlin {
experimental {
coroutines 'enable'
}
}
193
Module names
The Kotlin modules that the build produces are named accordingly to the archivesBaseName property of the project. If a project
has a broad name like lib or jvm , which is common for subprojects, the Kotlin output les related to the module
( *.kotlin_module ) might clash with those from third-party modules with the same name. This causes problems when a project
is packaged into a single archive (e.g. APK).
archivesBaseName = 'myExampleProject_lib'
Compiler Options
To specify additional compilation options, use the kotlinOptions property of a Kotlin compilation task.
When targeting the JVM, the tasks are called compileKotlin for production code and compileTestKotlin for test code. The
tasks for custom source sets of are called accordingly to the compile<Name>Kotlin pattern.
The names of the tasks in Android Projects contain the build variant names and follow the pattern
compile<BuildVariant>Kotlin , for example, compileDebugKotlin , compileReleaseUnitTestKotlin .
When targeting JavaScript, the tasks are called compileKotlin2Js and compileTestKotlin2Js respectively, and
compile<Name>Kotlin2Js for custom source sets.
compileKotlin {
kotlinOptions.suppressWarnings = true
}
compileKotlin {
kotlinOptions {
suppressWarnings = true
}
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
// ...
}
}
194
Name
jdkHome Description
Path to JDK home directory to include into classpath, if diers from default Possible Default
JAVA_HOME values value
jvmTarget Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6 "1.6", "1.8" "1.6"
noJdk Don't include Java runtime into classpath false
noReflect Don't include Kotlin reection implementation into classpath true
noStdlib Don't include Kotlin runtime into classpath true
Generating documentation
To generate documentation for Kotlin projects, use Dokka; please refer to the Dokka README for conguration instructions.
Dokka supports mixed-language projects and can generate output in multiple formats, including standard JavaDoc.
OSGi
For OSGi support see the Kotlin OSGi page.
Examples
The following examples show dierent possibilities of conguring the Gradle plugin:
Kotlin
Mixed Java and Kotlin
Android
JavaScript
195
Using Maven
Dene the version of Kotlin you want to use via a kotlin.version property:
<properties>
<kotlin.version>1.1.60</kotlin.version>
</properties>
Dependencies
Kotlin has an extensive standard library that can be used in your applications. Congure the following dependency in the pom
le:
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
If you're targeting JDK 7 or JDK 8, you can use extended versions of the Kotlin standard library which contain additional extension
functions for APIs added in new JDK versions. Instead of kotlin-stdlib , use kotlin-stdlib-jre7 or kotlin-stdlib-jre8 ,
depending on your JDK version.
If your project uses Kotlin reection or testing facilities, you need to add the corresponding dependencies as well. The artifact
IDs are kotlin-reflect for the reection library, and kotlin-test and kotlin-test-junit for the testing libraries.
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
</build>
196
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
197
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Incremental compilation
To make your builds faster, you can enable incremental compilation for Maven (supported since Kotlin 1.1.2). In order to do that,
dene the kotlin.compiler.incremental property:
198
<properties>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
</properties>
Annotation processing
See the description of Kotlin annotation processing tool ( kapt ).
Jar le
To create a small Jar le containing just the code from your module, include the following under build->plugins in your Maven
pom.xml le, where main.class is dened as a property and points to the main Kotlin or Java class:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Self-contained Jar le
To create a self-contained Jar le containing the code from your module along with dependencies, include the following under
build->plugins in your Maven pom.xml le, where main.class is dened as a property and points to the main Kotlin or Java
class:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals> <goal>single</goal> </goals>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
This self-contained jar le can be passed directly to a JRE to run your application:
199
Targeting JavaScript
In order to compile JavaScript code, you need to use the js and test-js goals for the compile execution:
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-js</goal>
</goals>
</execution>
</executions>
</plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-js</artifactId>
<version>${kotlin.version}</version>
For unit testing support, you also need to add a dependency on the kotlin-test-js artifact.
See the Getting Started with Kotlin and JavaScript with Maven tutorial for more information.
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>...</executions>
<configuration>
<nowarn>true</nowarn> <!-- Disable warnings -->
</configuration>
</plugin>
<project ...>
<properties>
<kotlin.compiler.languageVersion>1.0</kotlin.compiler.languageVersion>
</properties>
</project>
200
Name Property name Description Possible Default
values value
Generating documentation
The standard JavaDoc generation plugin ( maven-javadoc-plugin ) does not support Kotlin code. To generate documentation
for Kotlin projects, use Dokka; please refer to the Dokka README for conguration instructions. Dokka supports mixed-
language projects and can generate output in multiple formats, including standard JavaDoc.
OSGi
For OSGi support see the Kotlin OSGi page.
Examples
An example Maven project can be downloaded directly from the GitHub repository
201
Using Ant
These tasks are dened in the kotlin-ant.jar library which is located in the lib folder for the Kotlin Compiler Ant version 1.8.2+ is
required.
<target name="build">
<kotlinc src="hello.kt" output="hello.jar"/>
</target>
</project>
where ${kotlin.lib} points to the folder where the Kotlin standalone compiler was unzipped.
<target name="build">
<kotlinc output="hello.jar">
<src path="root1"/>
<src path="root2"/>
</kotlinc>
</target>
</project>
<target name="build">
<delete dir="classes" failonerror="false"/>
<mkdir dir="classes"/>
<javac destdir="classes" includeAntRuntime="false" srcdir="src">
<withKotlin/>
</javac>
<jar destfile="hello.jar">
<fileset dir="classes"/>
</jar>
</target>
</project>
202
To specify additional command line arguments for <withKotlin> , you can use a nested <compilerArg> parameter. The full list
of arguments that can be used is shown when you run kotlinc -help . You can also specify the name of the module being
compiled as the moduleName attribute:
<withKotlin moduleName="myModule">
<compilerarg value="-no-stdlib"/>
</withKotlin>
<target name="build">
<kotlin2js src="root1" output="out.js"/>
</target>
</project>
<target name="build">
<kotlin2js src="root1" output="out.js" outputPrefix="prefix" outputPostfix="postfix"
sourcemap="true"/>
</target>
</project>
<target name="build">
<!-- out.meta.js will be created, which contains binary metadata -->
<kotlin2js src="root1" output="out.js" metaInfo="true"/>
</target>
</project>
References
Complete list of elements and attributes are listed below:
kotlinc Attributes
203
Name Description Required Default Value
kotlin2js Attributes
204
Kotlin and OSGi
To enable Kotlin OSGi support you need to include kotlin-osgi-bundle instead of regular Kotlin libraries. It is recommended to
remove kotlin-runtime , kotlin-stdlib and kotlin-reflect dependencies as kotlin-osgi-bundle already contains all of
them. You also should pay attention in case when external Kotlin libraries are included. Most regular Kotlin dependencies are not
OSGi-ready, so you shouldn't use them and should remove them from your project.
Maven
To include the Kotlin OSGi bundle to a Maven project:
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-osgi-bundle</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
To exclude the standard library from external libraries (notice that "star exclusion" works in Maven 3 only):
<dependency>
<groupId>some.group.id</groupId>
<artifactId>some.library</artifactId>
<version>some.library.version</version>
<exclusions>
<exclusion>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
Gradle
To include kotlin-osgi-bundle to a gradle project:
compile "org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion"
To exclude default Kotlin libraries that comes as transitive dependencies you can use the following approach:
dependencies {
compile (
[group: 'some.group.id', name: 'some.library', version: 'someversion'],
.....) {
exclude group: 'org.jetbrains.kotlin'
}
FAQ
Why not just add required manifest options to all Kotlin libraries
Even though it is the most preferred way to provide OSGi support, unfortunately it couldn't be done for now due to so called
"package split" issue that couldn't be easily eliminated and such a big change is not planned for now. There is Require-Bundle
feature but it is not the best option too and not recommended to use. So it was decided to make a separate artifact for OSGi.
205
Compiler Plugins
For instance, when you use Spring, you don't need all the classes to be open, but only classes annotated with specic
annotations like @Configuration or @Service . All-open allows to specify such annotations.
We provide all-open plugin support both for Gradle and Maven with the complete IDE integration.
:point_up: For Spring you can use the kotlin-spring compiler plugin (see below).
Using in Gradle
Add the plugin artifact to the buildscript dependencies and apply the plugin:
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.plugin.allopen" version "1.1.60"
}
Then specify the list of annotations that will make classes open:
allOpen {
annotation("com.my.Annotation")
// annotations("com.another.Annotation", "com.third.Annotation")
}
If the class (or any of its superclasses) is annotated with com.my.Annotation , the class itself and all its members will become
open.
@com.my.Annotation
annotation class MyFrameworkAnnotation
@MyFrameworkAnnotation
class MyClass // will be all-open
Using in Maven
206
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<configuration>
<compilerPlugins>
<!-- Or "spring" for the Spring support -->
<plugin>all-open</plugin>
</compilerPlugins>
<pluginOptions>
<!-- Each annotation is placed on its own line -->
<option>all-open:annotation=com.my.Annotation</option>
<option>all-open:annotation=com.their.AnotherAnnotation</option>
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
Please refer to the "Using in Gradle" section above for the detailed information about how all-open annotations work.
Spring support
If you use Spring, you can enable the kotlin-spring compiler plugin instead of specifying Spring annotations manually. The kotlin-
spring is a wrapper on top of all-open, and it behaves exactly the same way.
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.plugin.spring" version "1.1.60"
}
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
The plugin species the following annotations: @Component, @Async, @Transactional, @Cacheable and @SpringBootTest.
Thanks to meta-annotations support classes annotated with @Configuration, @Controller, @RestController, @Service or
@Repository are automatically opened since these annotations are meta-annotated with @Component.
Of course, you can use both kotlin-allopen and kotlin-spring in the same project.
207
Note that if you use the project template generated by the start.spring.io service, the kotlin-spring plugin will be enabled by
default.
Using in CLI
All-open compiler plugin JAR is available in the binary distribution of the Kotlin compiler. You can attach the plugin by providing the
path to its JAR le using the Xplugin kotlinc option:
-Xplugin=$KOTLIN_HOME/lib/allopen-compiler-plugin.jar
You can specify all-open annotations directly, using the annotation plugin option, or enable the "preset". The only preset
available now for all-open is spring .
-P plugin:org.jetbrains.kotlin.allopen:annotation=com.my.Annotation
-P plugin:org.jetbrains.kotlin.allopen:preset=spring
The generated constructor is synthetic so it cant be directly called from Java or Kotlin, but it can be called using reection.
This allows the Java Persistence API (JPA) to instantiate the data class although it doesn't have the zero-parameter constructor
from Kotlin or Java point of view (see the description of kotlin-jpa plugin below).
Using in Gradle
Add the plugin and specify the list of annotations that must lead to generating a no-arg constructor for the annotated classes.
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.plugin.noarg" version "1.1.60"
}
noArg {
annotation("com.my.Annotation")
}
Enable invokeInitializers option if you want the plugin to run the initialization logic from the synthetic constructor. Starting
from Kotlin 1.1.3-2, it is disabled by default because of KT-18667 and KT-18668 which will be addressed in the future.
noArg {
invokeInitializers = true
}
208
Using in Maven
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<configuration>
<compilerPlugins>
<!-- Or "jpa" for JPA support -->
<plugin>no-arg</plugin>
</compilerPlugins>
<pluginOptions>
<option>no-arg:annotation=com.my.Annotation</option>
<!-- Call instance initializers in the synthetic constructor -->
<!-- <option>no-arg:invokeInitializers=true</option> -->
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
JPA support
As with the kotlin-spring plugin, kotlin-jpa is a wrapped on top of no-arg. The plugin species @Entity, @Embeddable and
@MappedSuperclass no-arg annotations automatically.
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.plugin.jpa" version "1.1.60"
}
<compilerPlugins>
<plugin>jpa</plugin>
</compilerPlugins>
Using in CLI
As with all-open, add the plugin JAR le to the compiler plugin classpath and specify annotations or presets:
209
-Xplugin=$KOTLIN_HOME/lib/noarg-compiler-plugin.jar
-P plugin:org.jetbrains.kotlin.noarg:annotation=com.my.Annotation
-P plugin:org.jetbrains.kotlin.noarg:preset=jpa
210
FAQ
FAQ
What is Kotlin?
Kotlin is an OSS statically typed programming language that targets the JVM, Android, JavaScript and Native. Its developed by
JetBrains. The project started in 2010 and was open source from very early on. The rst ocial 1.0 release was in February
2016.
Is Kotlin free?
Yes. Kotlin is free, has been free and will remain free. It is developed under the Apache 2.0 license and the source code is
available on GitHub.
Kotlin has both object-oriented and functional constructs. You can use it in both OO and FP styles, or mix elements of the two.
With rst-class support for features such as higher-order functions, function types and lambdas, Kotlin is a great choice if youre
doing or exploring functional programming.
What advantages does Kotlin give me over the Java programming language?
Kotlin is more concise. Rough estimates indicate approximately a 40% cut in the number of lines of code. Its also more type-
safe, e.g. support for non-nullable types makes applications less prone to NPEs. Other features including smart casting, higher-
order functions, extension functions and lambdas with receivers provide the ability to write expressive code as well as facilitating
creation of DSL.
Yes. Kotlin is 100% interoperable with the Java programming language and major emphasis has been placed on making sure that
your existing codebase can interact properly with Kotlin. You can easily call Kotlin code from Java and Java code from Kotlin. This
makes adoption much easier and lower-risk. Theres also an automated Java-to-Kotlin converter built into the IDE that simplies
migration of existing code.
Kotlin can be used for any kind of development, be it server-side, client-side web and Android. With Kotlin/Native currently in the
works, support for other platforms such as embedded systems, macOS and iOS is coming. People are using Kotlin for mobile
and server-side applications, client-side with JavaScript or JavaFX, and data science, just to name a few possibilities.
Yes. Kotlin is supported as a rst-class language on Android. There are hundreds of applications already using Kotlin for Android,
such as Basecamp, Pinterest and more. For more information check out the resource on Android development.
211
Yes. Kotlin is 100% compatible with the JVM and as such you can use any existing frameworks such as Spring Boot, vert.x or JSF.
In addition there are specic frameworks written in Kotlin such as Ktor. For more information check out the resource on server-
side development.
Yes. In addition to using for backend web, you can also use Kotlin/JS for client-side web. Kotlin can use denitions from
DenitelyTyped to get static typing for common JavaScript libraries, and it is compatible with existing module systems such as
AMD and CommonJS. For more information check out the resource on client-side development.
Yes. You can use any Java UI framework such as JavaFx, Swing or other. In addition there are Kotlin specic frameworks such as
TornadoFX.
Kotlin/Native is currently in the works. It compiles Kotlin to native code that can run without a VM. There is a Technology Preview
released but it is not production-ready yet, and doesnt yet target all the platforms that we plan to support for 1.0. For more
information check out the blog post announcing Kotlin/Native.
Kotlin is supported by all major Java IDEs including IntelliJ IDEA, Android Studio, Eclipse and NetBeans. In addition, a command line
compiler is available and provides straightforward support for compiling and running applications.
On the JVM side, the main build tools include Gradle, Maven, Ant, and Kobalt. There are also some build tools available that target
client-side JavaScript.
When targeting the JVM, Kotlin produces Java compatible bytecode. When targeting JavaScript, Kotlin transpiles to ES5.1 and
generates code which is compatible with module systems including AMD and CommonJS. When targeting native, Kotlin will
produce platform-specic code (via LLVM).
No. Kotlin lets you choose between generating Java 6 and Java 8 compatible bytecode. More optimal byte code may be
generated for higher versions of the platform.
Is Kotlin hard?
Kotlin is inspired by existing languages such as Java, C#, JavaScript, Scala and Groovy. We've tried to ensure that Kotlin is easy to
learn, so that people can easily jump on board, reading and writing Kotlin in a matter of days. Learning idiomatic Kotlin and using
some more of its advanced features can take a little longer, but overall it is not a complicated language.
There are too many companies using Kotlin to list, but some more visible companies that have publicly declared usage of Kotlin,
be this via blog posts, GitHub repositories or talks include Square, Pinterest or Basecamp.
Kotlin is primarily developed by a team of engineers at JetBrains (current team size is 40+). The lead language designer is
Andrey Breslav. In addition to the core team, there are also over 100 external contributors on GitHub.
The best place to start is this website. From there you can download the compiler, try it online as well as get access to
resources, reference documentation and tutorials.
212
Are there any books on Kotlin?
There are already a number of books available for Kotlin, including Kotlin in Action which is by Kotlin team members Dmitry
Jemerov and Svetlana Isakova, Kotlin for Android Developers targeted at Android developers.
There are a few courses available for Kotlin, including a Pluralsight Kotlin Course by Kevin Jones, an OReilly Course by Hadi Hariri
and an Udemy Kotlin Course by Peter Sommerho.
There are also many recordings of Kotlin talks available on YouTube and Vimeo.
Yes. Kotlin has a very vibrant community. Kotlin developers hang out on the Kotlin forums, StackOverow and more actively on
the Kotlin Slack (with close to 7000 members as of May 2017).
Yes. There are many User Groups and Meetups now focused exclusively around Kotlin. You can nd a list on the web site. In
addition there are community organised Kotlin Nights events around the world.
Yes. The rst ocial KotlinConf, taking place in San Francisco 2-3 November 2017. Kotlin is also being covered in dierent
conferences worldwide. You can nd a list of upcoming talks on the web site.
Yes. The most active Kotlin account is on Twitter. There is also a Google+ group.
The web site has a bunch of online resources, including Kotlin Digests by community members, a newsletter, a podcast and
more.
Logos can be downloaded here. Please follow simple rules in the guidelines.pdf inside the archive.
213
Comparison to Java Programming Language
214
215