What is Kotlin?
Kotlin is a general-purpose language aimed at making developers happier! Created by JetBrain(the creators of IntelliJ IDEA), Kotlin is concise, safe, interoperable with Java and other languages, and provides many ways to reuse code between multiple platforms for productive programming.
Start your first line of Kotlin with “Hello World”!
fun main() { println("Hello World")}
OUTPUT: Hello World
Basic Concepts and Syntax
The first step to mastering a new programming language is to know all the basics (variables, control structures, syntax) before moving on to the next level. By following this path you will definitely save yourself a lot of time learning how to code 🙂
You will learn the basic syntax and concepts of Kotlin in this section. You will be able to easily learn the advanced concepts of Kotlin once you have these in mind.
You can read Kotlin doc for a complete introduction to the language.
Print to the standard output
The print function prints whatever you specify to your console window. It is actually a very good debugging tool. If something isn’t acting right, you can use the print function to see what is going on in the program.
In Kotlin, the print
prints its argument to the standard output:
print("Hello ")
print("world!")
OUTPUT: Hello World!
println
prints its arguments and adds a line break, so that the next thing you print appears on the next line:
println("Hello world!")
println(42)
OUTPUT: Hello World!
42
Comments
Comments are text notes added to the program to provide explanatory information about the source code. A good programmer always writes comments for their codes. In a large project or framework, you will usually find more than half the code is comments.
Just like most modern languages, Kotlin supports single-line (or end-of-line) and multi-line (block) comments:
// This is an end-of-line comment
/* This is a block comment
on multiple lines. */
Variables
Variables serve as a way to store and retrieve information. They also label data with descriptive names.
In Kotlin, read-only local variables are defined using the keyword val
. It can only be assigned a value once:
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
Variables that can be reassigned use the var
keyword:
var x = 5 // `Int` type is inferred
x += 1
Data Types
Data types are a very simple yet extremely important concept found in almost all programming languages. Essentially, data types represent the various types of data your program can handle. As a result, the computer may store and process data of different types in different ways. In this section, we describe the basic types used in Kotlin: numbers, booleans, characters, strings, and arrays.
Numbers
Kotlin provides a set of built-in types that represent numbers.
Type | Size(bits) | Byte | 8 |
---|---|
Short | 16 |
Int | 32 |
Long | 64 |
Float | 32 |
Double | 64 |
All variables initialized with integer values not exceeding the maximum value of Int have the inferred type Int:
val one = 1 // Int
val threeBillion = 3000000000 // Long
val oneLong = 1L // Long
val oneByte: Byte = 1
For variables initialized with fractional numbers, the compiler infers the Double
type:
val pi = 3.14 // Double
// val one: Double = 1 // Error: type mismatch
val oneDouble = 1.0 // Double
Kotlin supports the standard set of arithmetical operations over numbers: +
, -
, *
, /
, %
:
println(1 + 2)
println(2_500_000_000L - 1L)
println(3.14 * 2.71)
println(10.0 / 3)
OUTPUT: 3
2499999999
8.5094
3.3333333333333335
Boolean
The type Boolean
represents boolean objects that can have two values: true
and false
.
val myTrue: Boolean = true
val myFalse: Boolean = false
Built-in operations on booleans include:
println(myTrue || myFalse) \\ disjunction (logical OR)
println(myTrue && myFalse) \\ conjunction (logical AND)
println(!myTrue) \\ negation (logical NOT)
OUTPUT: true
false
false
Characters and String
Characters are represented by the type Char
. Character literals go in single quotes: ‘1’.
val aChar: Char = 'a'
println(aChar)
println('\n') //prints an extra newline character
OUTPUT: a
Strings in Kotlin are represented by the type String
. Generally, a string value is a sequence of characters in double quotes (“”).
val s = "Hello, world!\n"
String literals may contain template expressions – 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 name or an expression in curly braces:
val s = "abc"
println("$s.length is ${s.length}") // prints "abc.length is 3"
OUTPUT: abc.length is 3
Array
Arrays in Kotlin are represented by the Array
class. To create an array, use the function arrayOf()
and pass the item values to it, so that arrayOf(1, 2, 3)
creates an array [1, 2, 3]
. Another option is to use the Array constructor that takes the array size and the function that returns values of array elements given its index:
// Creates an Array String with values ["0", "1", "4", "9", "16"]
val asc = Array(5) { i -> (i * i).toString() }
asc.forEach { println(it) }
Kotlin also has classes that represent arrays of primitive types without boxing overhead: ByteArray
, ShortArray
, IntArray
, and so on.
val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]
For more information, please refer to Types.
Nullable Reference
Null is a placeholder that means that is not an integer, not a string, not a boolean – not anything really, except something to hold and be a “not there” value. Kotlin aims at eliminating the danger of null references, also known as The Billion Dollar Mistake.
In Kotlin, the type system distinguishes between references that can hold null
(nullable references) and those that cannot (non-null references). For example, a regular variable of type String
cannot hold null
:
var a: String = "abc" // Regular initialization means non-null by default
a = null // compilation error
To allow nulls, you can declare a variable as a nullable string by writing String?
:
var b: String? = "abc" // can be set to null
b = null // ok
print(b)
OUTPUT: null
For more information, please refer to Null-Safety.
Control Flow
The control flow is the order in which the computer executes statements in a script. The figure below shows four examples of control flow and the corresponding flow chart.

Conditional expressions
In Kotlin, if
is an expression: it returns a value. If you’re using if
as an expression, for example, for returning its value or assigning it to a variable, the else
the branch is mandatory:
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
when
defines a conditional expression with multiple branches. It matches its argument against all branches sequentially until some branch condition is satisfied.
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}
Loop
The for
loop iterates through anything that provides an iterator. For example, if you want to iterate through an array or a list with an index, you can do it this way:
fun main() {
val array = arrayOf("a", "b", "c")
for (i in array.indices) {
println(array[i])
}
}
OUTPUT: a
b
c
while
loop executes its body continuously while the condition is satisfied:
while (x -> 0) {
x--
}
For more information, please refer to Conditions and Loops.
Exceptions
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program’s instructions.
In Kotlin, to throw an exception object, use the throw
expression:
fun main() {
throw Exception("Hi There!")
}
OUTPUT: Exception in thread "main" java.lang.Exception: Hi There!
To catch an exception, use the try
… catch
expression. There may be zero or more catch
blocks, and the finally
block may be omitted. However, at least one catch
or finally
block is required:
try {
// Block 1: some code
} catch (e: SomeException) {
// Block 2: handler
} finally {
// Block 3: optional finally block
}
For more information, please refer to Exceptions.
Functions
Functions are a set of instructions bundled together to achieve a specific outcome. Functions increase the reusability of code. The values can be sent to a function using variables – these are called parameters or arguments. Functions may also return values.

Kotlin functions are declared using the fun
keyword. Function parameters can have default values, which are used when you skip the corresponding argument:
fun double(x: Int = 0): Int {
return 2 * x
}
If a function does not return a 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:
fun printHello(name: String?): Unit {
if (name != null)
println("Hello $name")
else
println("Hi there!")
// `return Unit` or `return` is optional
}
printHello("Kotlin")
OUTPUT: Hello Kotlin
Functions with block bodies must always specify return types explicitly unless it’s intended for them to return Unit
, in which case specifying the return type is optional.
For more information, please refer to Functions.
Creating classes and instances
Class is a very important concept in Object-oriented programming languages like Kotlin. In code, we combine a group of related variables and functions into a unit, we called that unit an object. Classes are the blueprints that define the behavior and information our objects will contain. An instance method is the behavior of Objects.
The bear doodles below reveal the relationship between class and instance. The class ‘Bear’ is a bear doodle template with ‘color’ and ’emotion’ attributes. These three instances of bear have different values of the attributes when they are created from the ‘Bear’ Class.

Classes in Kotlin are declared using the keyword class
:
class InitOrderDemo(name: String) {
val firstProperty = "First property: $name".also(::println)
init {
println("First initializer block that prints ${name}")
}
val secondProperty = "Second property: ${name.length}".also(::println)
init {
println("Second initializer block that prints ${name.length}")
}
}
fun main() {
InitOrderDemo("hello")
}
First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5
The class declaration consists of the class name, the class header (specifying its type parameters, the primary constructor, and some other things), and the class body surrounded by curly braces. Initialization code can be placed in initializer blocks prefixed with the init
keyword. During the initialization of an instance, the initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers.
To create an instance of a class, call the class constructor as if it were a regular function:
val invoice = Invoice()
val customer = Customer("Joe Smith")
Classes can contain:
- Constructors and initializer blocks
- FunctionsProperties
- Nested and inner classes
- Object declarations
For more information, please refer to Class.
Package definition and imports
A package is a namespace that organizes a set of related classes and interfaces. Conceptually you can think of packages as being similar to different folders on your computer. A source file may start with a package
declaration:
//This is file A
package org.example
fun printMessage() { /*...*/ }
class Message { /*...*/ }
Apart from the default imports, each file may contain its own import
directives.
// This is file B
import org.example.Message // Message is now accessible without qualification
import org.test.* // everything in 'org.test' becomes accessible
For more information, please refer to Packages.