The following example demonstrates features and concepts in Kotlin including:
- Defining a data class with properties without the need to specify a body
- Declaring read-only properties with the
val
keyword - Providing default values for arguments
- Explicit nullable values (
Int?
) in the type system - Top-level function definitions without nesting them inside classes
- Named arguments when invoking functions and constructors
- Using trailing commas
- Using collection operations with lambda expressions
- Providing fallback values when a variable is
null
via the Elvis operator (?:
) - Using string templates as an alternative to manual concatenation
- Using autogenerated functions for data classes, such as
toString
data class Person(
val name: String,
val age: Int? = null,
)
fun main() {
val persons =
listOf(
Person("Alice", age = 29),
Person("Bob"),
)
val oldest =
persons.maxBy {
it.age ?: 0
}
println("The oldest is: $oldest")
}
// The oldest is: Person(name=Alice, age=29)
Kotlin is a statically typed programming language; the compiler can validate that the methods and fields you're trying to access on an object actually exist.
The ability of the compiler to determine types from context is called type inference. Type inference in Kotlin means that most of the extra verbosity associated with static typing disappears because you don't need to declare types explicitly.
Kotlin supports nullable types.
Kotlin's type system also has first-class support for function types.
The key concepts of functional programming are as follows:
- First class functions: You work with functions as values. You can store them in variables, pass them as parameters, or return them from other functions.
- Immutability: You work with immutable objects, which guarantees their state can't change after their creation.
- No side effects: You write pure functions, functions that return the same result given the same inputs and don't modify the state of other objects.
The benefits of functional programming are conciseness, safe concurrency, and easier testing.
Kotlin's support for functional programming includes:
- Function types: Allowing functions to receive other functions as arguments or return other functions
- Lambda expressions: Letting you pass around blocks of code with minimum boilerplate
- Member references: Allowing you to use functions as values and, for instance, pass them as arguments
- Data classes: Provide a concise syntax for creating classes that can hold immutable data
- Standard library APIs: A rich set in the standard library for working with objects and collections in the functional style
Kotlin approaches the problem of concurrent and asynchronous programming using suspendable computations called coroutines, where code can suspend its execution and resume its work at a later point.
Structured concurrency helps you manage the lifetime of your coroutines.
Coroutines are also a very lightweight abstraction, meaning you can launch millions of concurrent jobs without significant performance penalties. Together with abstractions, like cold and hot flows, Kotlin coroutines become a powerful tool for building concurrent applications.
Kotlin code can be compiled to different targets:
- JVM bytecode (stored in .class files) to run on the JVM
- JVM bytecode to be further transformed and run on Android
- Native targets to run natively on different systems
- JavaScript (and WebAssembly) to run in a browser
Kotlin source code is normally stored in files with the extension .kt. When compiling Kotlin code for the JVM target, compiler analyzes the source code and generated .class files, just like the Java compiler. The generated .class files are then packaged and executed using the standard procedure for the type of application you're working on.
In simple cases, use kotlinc
command to compile your code, then use java
command to execute the code:
kotlinc <source file or directory> -include-runtime -d <jar name>
java -jar
Kotlin built-in classes and their APIs differ from those in Java, and to correctly run the compiled code, JVM needs the additional information as a dependency: the Kotlin runtime library.
The Kotlin runtime library contains the definitions of Kotlin's basic classes, like Int
and String
, and some extensions Kotlin adds to the standard Java APIs.
Additionally, you need the Kotlin standard library included as a dependency. The standard library contains the definitions of such fundamental classes as List
, Map
, and Sequence
as well as many methods for working with them.
Maven and Gradle take care of including both the Kotlin runtime library and (for the latest versions) Kotlin start library as dependencies.