This is a practical guide on kotlin language. This one file can be used as your pocket reference if you had already mastered the language or a life savior for the newbies who are looking for a short and simple tutorial.
I will try to update it frequently, but you can feel free to add examples in codes/ directory or commit changes in readme file
- Preface
- Introduction
- Basics
- Conditionals
- Functions
- Exception Handling
- NULL Safety
- Collections
- Classes
- Misc
Kotlin is a cross-platform, statically typed, general-purpose programming language with type inference
Every kotlin program starts from the main function, as demonstrated below
fun main(args: Array<String>) {
// your code
}NOTE : Since this is an interactive notebook, the main function part will be skipped.
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/println.html#println
println("Hello World")Hello World
Variables are used to store the value of specific type, the types supported by kotlin there in documentation
Documentation: https://kotlinlang.org/docs/reference/basic-types.html, https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/
var age: Int = 22
age22
Changing value of the variable
age = 30
age30
Kotlin support three types of variables
var→ mutable variables, values of such variables can be changed during the program setval→ immutable variables, values of such variables can be initialized only single time
val i = 10
i10
i = 20Val cannot be reassigned
i10
Using underscored number literal
val oneMillion = 1_000_000
oneMillion1000000
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-float/
// the f means to use floating number, otherwise it will use the double and then type cast it into float
val price: Float = 44.77f;
price44.77
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/
var name: String = "Gurkirat Singh"
nameGurkirat Singh
Length of string
name.length14
Getting one character
name[0] == name.get(0)true
Comparing two strings
val name2 = "Gurkirat Singh"
name2Gurkirat Singh
name == name2true
name.compareTo(name2)0
Here 0 means both strings are identical
Concatenating two strings
name.plus(name2)Gurkirat SinghGurkirat Singh
name + name2Gurkirat SinghGurkirat Singh
Collection of similar type of data
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/
var numbers = arrayOf(1, 2, 3, 4, 5, 6)
numbers[Ljava.lang.Integer;@728561a2
To get the value, use the index number
numbers[0]1
numbers[4]5
Getting the length of array
numbers.size6
Empty array of specific type
val emptyArray = arrayOf<Int>()
emptyArray[Ljava.lang.Integer;@303524fb
emptyArray.size0
val num1 = 1
val num2 = "2"Both look identical (numbers), but the type of both the variables are not same
num1 + num2None of the following functions can be called with the arguments supplied:
public final operator fun plus(other: Byte): Int defined in kotlin.Int
public final operator fun plus(other: Double): Double defined in kotlin.Int
public final operator fun plus(other: Float): Float defined in kotlin.Int
public final operator fun plus(other: Int): Int defined in kotlin.Int
public final operator fun plus(other: Long): Long defined in kotlin.Int
public final operator fun plus(other: Short): Int defined in kotlin.Int
num1 + num2.toInt()3
Documentation: https://kotlinlang.org/docs/reference/keyword-reference.html#operators-and-special-symbols
val num1 = 20
val num2 = 30Addition
num1 + num250
Subtraction
num2 - num110
Multiplication
num1 * num2600
Division
num2 / num11
num2.toFloat() / num1.toFloat()1.5
Finding remainder
num2 % num110
val num1 = 20
val num2 = 30Equality
num1 == num2false
NOTE: Don't misunderstand == with =. First one is called equal to operator and another is called assignment operator (evaluates and assigns the RHS value to LHS)
Less than
num1 < num2true
num2 < num2false
Greater than
num1 > num2false
Greater than equal to
num1 >= num1true
Less than equal to
num1 <= num1true
Not equal to
num1 != num2true
var num1 = 10
num110
Post increment
num1++
num111
Pre increment
++num1
num112
Post decrement
num1--
num111
Pre decrement
--num1
num110
var num1 = 10
var num2 = 20num1.toString(2)1010
num2.toString(2)10100
Shift left by one bit
num1 = num1.shl(1)
num1.toString(2)10100
Shift right by one bit
num1 = num1.shr(1)
num1.toString(2)1010
Bitwise or
num1.or(num2).toString(2)11110
Bitwise and
num1.and(num2).toString(2)0
Bitwise xor
num1.xor(num2).toString(2)11110
num1.and(num1).toString(2)1010
Bitwise inverse
num1.inv().toString(2)-1011
num1.inv()-11
AND operator
true && truetrue
false && truefalse
true && falsefalse
false && falsefalse
OR operator
true || truetrue
true || falsetrue
false || truetrue
false || falsefalse
NOT Operator
true && !falsetrue
Documentation: https://kotlinlang.org/docs/reference/control-flow.html#if-expression
var age = 18
var age2 = 14if (age >= 18) {
println("You are an adult")
}
else {
println("Hey kiddo")
}You are an adult
if (age2 >= 18) {
println("You are an adult")
}
else {
println("Hey kiddo")
}Hey kiddo
Documentation: https://kotlinlang.org/docs/reference/control-flow.html#when-expression
var num = 4when(num) {
1 -> println("Sunday")
2 -> println("Monday")
3 -> println("Tuesday")
4 -> println("Wednesday")
5 -> println("Thursday")
6 -> println("Friday")
7 -> println("Saturday")
else -> println("Number should be in between 1 and 7") // will be executed if no value matches
}Wednesday
To run same lines of code for multiple choices
when(variable) {
1, 2, 3 -> println("your input is either 1 or 2 or 3")
else -> {
// running multiple lines
println("This is not a joke")
println("Enter number 1, 2, 3 only")
}
}To run same lines of code for a range of numbers
when(variable) {
in 1..3 -> println("your input is either 1 or 2 or 3")
else -> {
// running multiple lines
println("This is not a joke")
println("Enter number 1, 2, 3 only")
}
}Documentation: https://kotlinlang.org/docs/reference/control-flow.html#for-loops
var numbers = arrayOf<Int>(1, 2, 3, 4, 5, 6)Simple demonstration
for (number in numbers){
println(number)
}1
2
3
4
5
6
With indices
for ((idx, number) in numbers.withIndex()) {
println("number '$number' is at index '$idx' in the array")
}number '1' is at index '0' in the array
number '2' is at index '1' in the array
number '3' is at index '2' in the array
number '4' is at index '3' in the array
number '5' is at index '4' in the array
number '6' is at index '5' in the array
Range based loop
for (i in 1..5)
{
println(i)
}1
2
3
4
5
Range based loop with step
for (i in 1..5 step 2)
{
println(i)
}1
3
5
Reverse loop with step
for (i in 6 downTo 0 step 2)
{
println(i)
}6
4
2
0
Documentation: https://kotlinlang.org/docs/reference/control-flow.html#while-loops
var num = 5while (num > 0)
{
println(num--)
}5
4
3
2
1
do {
println(num--)
} while (num > 0)0
Difference between while and do-while loop: https://stackoverflow.com/a/3347010/10362396
Jump statements like break and continue are used to end and skip the following loop body.
Documentation: https://kotlinlang.org/docs/reference/returns.html#returns-and-jumps
A function is a unit of code that performs a special task. In programming, function is used to break the code into smaller modules which makes the program more manageable.
Documentation: https://kotlinlang.org/docs/reference/functions.html#function-declarations
fun greet() {
println("Hello User")
}greet()Hello User
fun sum(x: Int, y: Int) {
println(x+y)
}sum(10, 11)21
Calling function with wrong type
sum(10.4f, 11)The floating-point literal does not conform to the expected type Int
fun say_hello(name: String) : String {
return "Hello, " + name
}say_hello("John")Hello, John
say_hello("Dale")Hello, Dale
A function which calls itself is called as recursive function and this process of repetition is called recursion.
fun factorial(num: Int): Int {
// base condition
if (num <= 1) {
return 1
}
// function calling itself
return num * factorial(num - 1)
}factorial(5)120
Documentation: https://kotlinlang.org/docs/reference/functions.html#default-arguments
fun say_hello_default(name: String = "Guest"): String {
return "Hello, " + name
}say_hello_default()Hello, Guest
say_hello_default("Sheldon")Hello, Sheldon
Documentation: https://kotlinlang.org/docs/reference/functions.html#named-arguments
fun say_hello_default_name(name: String = "Guest", robot: String): String {
return "Hello, " + name + ". I am " + robot
}say_hello_default_name(robot = "Alex")Hello, Guest. I am Alex
say_hello_default_name("Dale", robot = "Alice")Hello, Dale. I am Alice
The lambda functions are the functions that are not declared, but passed immediately as an expression
Documentation: https://kotlinlang.org/docs/reference/lambdas.html#lambda-expressions-and-anonymous-functions
fun multiply(x: Int, y: Int, callback: (Int) -> Unit)
{
callback(x * y)
}var cb: (Int) -> Unit = {p -> println("The product is $p") } // lambda function
multiply(10, 20, cb)The product is 200
Function that accept functions as the parameters and can return function as a value. This is basically implemented by the lambda functions
Documentation: https://kotlinlang.org/docs/reference/lambdas.html#higher-order-functions
var fn:(Int, Int) -> Int = {x, y-> x + y};
fun adder(num1: Int, num2: Int, callback: (Int, Int) -> Int): Int {
return callback(num1, num2)
}adder(10, 20, fn)30
Documentation: https://kotlinlang.org/docs/reference/inline-functions.html
inline fun inlineFunc(myFunc: () -> Unit): Unit {
myFunc()
}inlineFunc({println("Printing inside inline function")})Printing inside inline function
Documentation: https://kotlinlang.org/docs/tutorials/kotlin-for-py/exceptions.html#throwing-and-catching
var num1 = 100
var num2 = 0try {
num1 / num2
} catch (e: ArithmeticException) {
println("Attempted divide by zero")
}Attempted divide by zero
fun toInt(v: String): Int {
return try {
Integer.parseInt(v)
} catch (e: NumberFormatException) {
0
}
}toInt("10")10
toInt("hello")0
The finally blocks runs regardless of the successful or failed execution
try {
// some code
} catch (e: Exception) {
//some execption
} finally {
// this will run after try or catch block execution
}fun divMe(x: Int, y: Int): Int {
if (y < 0){
throw IllegalArgumentException("y should be strictly greater than 0")
}
return x / y
}try {
divMe(10, 0)
} catch (e: ArithmeticException) {
print("Aborted: ")
println(e)
} catch (e: IllegalArgumentException) {
print("Aborted: ")
println(e)
}Aborted: java.lang.ArithmeticException: / by zero
try {
divMe(10, -20)
} catch (e: ArithmeticException) {
print("Aborted: ")
println(e)
} catch (e: IllegalArgumentException) {
print("Aborted: ")
println(e)
}Aborted: java.lang.IllegalArgumentException: y should be strictly greater than 0
Documentation: https://kotlinlang.org/docs/reference/null-safety.html#nullable-types-and-non-null-types
var myVar: Int = 7
myVar7
myVar = 10
myVar10
myVar = nullNull can not be a value of a non-null type Int
Use Int? while defining the variable, so as to accept null values
var myVar: Int? = 7
myVar7
myVar = 10
myVar10
myVar = null
myVarDocumentation: https://kotlinlang.org/docs/reference/null-safety.html#safe-casts
var num: Int? = 19
num = nullvar num2: Int? = num as? Int
num2num = 10var num2: Int? = num as? Int
num210
Documentation: https://kotlinlang.org/docs/reference/null-safety.html#elvis-operator
val s1: String? = null;
val s2: String? = "Hello World";var l1: Int = if (s1 != null) s1.length else -1
l1-1
var l2: Int = if (s2 != null) s2.length else -1
l211
Simplifying the above with elvis operator
var l1: Int = s1 ?.length ?: -1
l1-1
var l2: Int = s2 ?.length ?: -1
l211
Documentation:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/list-of.html
var numbers = listOf(1, 2, "3", 4, 5)
for (number: Any in numbers) {
println(number)
}1
2
3
4
5
List with type specification
var numbers = listOf<Int>(1, 2, 3, 4, 5)
for (number: Int in numbers) {
println(number)
}1
2
3
4
5
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/mutable-list-of.html
var list = mutableListOf<Int>()list.isEmpty()true
list.size0
Adding an element
list.add(10)
list.size1
list[0]10
Adding multiple elements
list.addAll(listOf(20, 30, 40))
list.size4
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/array-list-of.html
var array = arrayListOf<Int>(10, 20, 30)
for(element in array) {
println(element)
}10
20
30
array.add(100)
for(element in array) {
println(element)
}10
20
30
100
array[2] = -100
for(element in array) {
println(element)
}10
20
-100
100
Inserting at specific location
array.add(1, -200)
for(element in array) {
println(element)
}10
-200
20
-100
100
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-map/
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-of.html
var map: Map<String, Int> = mapOf<String, Int>("ONE" to 1, "TWO" to 2)map["ONE"]1
map.keys[ONE, TWO]
for (key in map.keys) {
println(map[key])
}1
2
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/mutable-map-of.html
var map = mutableMapOf<Int, String>(10 to "TEN", 20 to "TWENTY")
map{10=TEN, 20=TWENTY}
map[10]TEN
map[30] = "THIRTY"for(key in map.keys) {
println(map[key])
}TEN
TWENTY
THIRTY
It is an implementation of the interface MutableMap
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-hash-map/
var hmap: HashMap<Int, String> = HashMap<Int, String>();
// HashMap<Int, String>(initalCapacity) use this to reserve the memory while initilization
// you can add more keys later onhmap.put(1, "Spiderman")
hmap.put(2, "Ironman")
hmap.put(3, "Black Widow")
hmap.put(4, "Ant Man")hmap[1]Spiderman
hmap.get(2)Ironman
hmap.keys[1, 2, 3, 4]
for(key in hmap.keys) {
println(hmap[key])
}Spiderman
Ironman
Black Widow
Ant Man
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/hash-map-of.html
var hmap = hashMapOf<Int, Int>(1 to 10, 2 to 20)
hmap.size2
for(key in hmap.keys) {
println(hmap[key])
}10
20
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-set/#kotlin.collections.Set
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/set-of.html
var set1 = setOf(1, 2, 3, 4, 4, 2, 3)
set1[1, 2, 3, 4]
for(element in set1){
println(element)
}1
2
3
4
set1.contains(1)true
set1.contains(10)false
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/mutable-set-of.html
val set2 = mutableSetOf<Int>()set2.add(1)
set2.add(1)
set2.add(2)
set2.add(2)
set2.add(3)true
set2[1, 2, 3]
for(element in set2) {
println(element)
}1
2
3
set2.remove(1)true
set2.remove(5)false
for(element in set2) {
println(element)
}2
3
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/hash-set-of.html
val set3 = hashSetOf<Int>(1, 2, 3, 5)
set3[1, 2, 3, 5]
for(el in set3) {
println(el)
}1
2
3
5
Documentation: https://kotlinlang.org/docs/tutorials/kotlin-for-py/classes.html#declaration-and-instantiation
class Vehicle {
// class properties
var speed: Int = 0
var wheels: Int = 0
var model: String = ""
// class methods
fun SetModel(m: String) {
model = m
}
fun SetSpeed(s: Int) {
speed = s
}
}var vehicle1 = Vehicle()vehicle1Line_166_jupyter$Vehicle@6400abd0
vehicle1.modelvehicle1.SetModel("BMW")vehicle1.modelBMW
vehicle1.wheels0
vehicle1.wheels = 4
vehicle1.wheels4
Documentation: https://kotlinlang.org/docs/reference/nested-classes.html#nested-and-inner-classes
class C1 {
fun ShowMe() {
println("From Outer Class C1")
}
class C2 {
fun ShowMe() {
println("From Inner Class C2")
}
}
}var c1 = C1()
c1.ShowMe()From Outer Class C1
var c2 = C1.C2()
c2.ShowMe()From Inner Class C2
Documentation: https://kotlinlang.org/docs/reference/classes.html#constructors
class Car {
var wheels: Int
var model: String
init {
println("Starting the car")
wheels = 4
model = "BMW"
}
fun Stop() {
println("Stopping the car")
}
}var car = Car()Starting the car
car.wheels4
car.Stop()Stopping the car
class Vehicle(_wheels: Int, _model: String) {
var wheels: Int
var model: String
init {
println("starting")
wheels = _wheels
model = _model
}
fun Stop() {
println("stopping")
}
}var v1 = Vehicle(4, "BMW")
var v2 = Vehicle(2, "Kawasaki Ninka")starting
starting
v1.wheels4
v2.wheels2
v1.Stop()
v2.Stop()stopping
stopping
NOTE: Keyword init can be used multiple times
class InitOrderDemo(name: String) {
val firstProperty = "First property: $name"
init {
println("First initializer block that prints ${name}")
}
val secondProperty = "Second property: ${name.length}"
init {
println("Second initializer block that prints ${name.length}")
}
}
InitOrderDemo("hello")First initializer block that prints hello
Second initializer block that prints 5
Line_186_jupyter$InitOrderDemo@7435796a
Documentation: https://kotlinlang.org/docs/reference/classes.html#secondary-constructors
class Person {
var name: String;
var age: Int;
constructor(name: String, age: Int) {
this.name = name;
this.age = age;
}
fun whoami() {
println("I am $name and I am $age years old.")
}
}var p1 = Person("John", 23)
var p2 = Person("Sarrah", 44)p1.whoami()I am John and I am 23 years old.
p2.whoami()I am Sarrah and I am 44 years old.
Documentation: https://kotlinlang.org/docs/reference/visibility-modifiers.html#classes-and-interfaces
class Person {
private var name: String;
constructor(name: String) {
this.name = name
}
fun whoami(): String {
return "I am $name"
}
}var p1 = Person("Joel")p1.whoami()I am Joel
p1.nameCannot access 'name': it is private in 'Person'
Documentation: https://kotlinlang.org/docs/reference/classes.html#inheritance
open class Vehicle {
public var wheels: Int = 0;
public var model: String = "";
fun Start() {
println("Starting")
}
fun Stop() {
println("Stop")
}
}class Car: Vehicle {
constructor(model: String, wheels: Int) {
this.wheels = wheels
this.model = model
}
}var car = Car("BMW", 4)car.Start()Starting
car.modelBMW
car.Stop()Stop
Documentation: https://kotlinlang.org/docs/reference/classes.html#overriding-methods
open class Vehicle {
public var wheels: Int
constructor(wheels: Int) {
this.wheels = wheels
}
open fun Start() {
println("Starting the vehicle")
}
open fun Stop() {
println("Stopping the vehicle")
}
}class Car(_wheels: Int): Vehicle(_wheels) {
init {
this.wheels = _wheels;
}
override fun Start() {
println("Starting the car")
}
override fun Stop() {
println("Stopping the car")
}
}var car = Car(4)
car.wheels4
car.Start()Starting the car
car.Stop()Stopping the car
Documentation: https://kotlinlang.org/docs/reference/classes.html#overriding-properties
open class Shape {
open protected val ndims: Int = 0
fun getDims(): Int {
return this.ndims
}
}class Rectangle : Shape() {
override protected val ndims = 4
}var rect = Rectangle()rect.getDims()4
rect.ndimsCannot access 'ndims': it is protected in 'Rectangle'
Documentation: https://kotlinlang.org/docs/reference/classes.html#abstract-classes
abstract class Shape(_n: Int) {
protected var ndims: Int
init {
this.ndims = _n
}
public fun getDims(): Int {
return this.ndims
}
}class Rect: Shape(4) {
}var rect = Rect()
rect.getDims()4
open class Person {
open fun sayHello() {
println("Hello from super class")
}
}
class Student: Person {
constructor() : super() {}
override fun sayHello() {
println("Hello from sub class")
super.sayHello()
}
}var student = Student()student.sayHello()Hello from sub class
Hello from super class
Documentation: https://kotlinlang.org/docs/reference/data-classes.html#data-classes
data class Student(var name: String, var age: Int);var student: Student = Student("John", 22)
studentStudent(name=John, age=22)
student.nameJohn
student.age22
Documentation: https://kotlinlang.org/docs/reference/whatsnew11.html#sealed-and-data-classes
sealed class Shape {
data class Circle (var radius: Int)
data class Rectangle (var width: Int, var height: Int)
data class Square (var side: Int)
}var c = Shape.Circle(20)
cCircle(radius=20)
var r = Shape.Rectangle(20, 10)
rRectangle(width=20, height=10)
var s = Shape.Square(20)
sSquare(side=20)
Documentation: https://kotlinlang.org/docs/reference/extensions.html#extension-functions
class Person {}
fun Person.sayHello(): String {
return "Hello"
}var p = Person()
p.sayHello()Hello
Documentation: https://kotlinlang.org/docs/reference/functions.html#generic-functions
fun <T> Return(x: T): T {
return x
}Return<Int>(5)5
Return<String>("Hello")Hello
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/
var str = "Hello world at 10:22!!"var pattern = Regex("[0-9]{2}:[0-9]{2}")pattern[0-9]{2}:[0-9]{2}
pattern.containsMatchIn(str)true
pattern.findAll(str)kotlin.sequences.GeneratorSequence@53db2a04
Documentation: https://kotlinlang.org/docs/reference/java-interop.html
System.out.println("Hello")Hello
Like Java, it also supports imports
Documentation: https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html
filename: main.kt
fun main() {
}
fun Print() {
println("Calling from kotlin file")
}filename: app.java
public class app
{
public static void main() {
MainKt.Print()
}
}