valimmutable:String="Cannot be changed"// Read-only (immutable)varmutable:String="Can be changed"// Mutablemutable="New value"// Type inferencevalinferred="Type is inferred as String"
Basic Types
// Numbersvalbyte:Byte=127// 8 bitsvalshort:Short=32767// 16 bitsvalint:Int=2147483647// 32 bitsvallong:Long=9223372036854775807L// 64 bitsvalfloat:Float=3.14f// 32 bitsvaldouble:Double=3.14159// 64 bits// Characters and stringsvalchar:Char='A'valstring:String="Hello"valmultiline:String="""
This is a
multiline string
No escaping needed
"""// Booleanvalboolean:Boolean=true// Type conversionvallongFromInt:Long=int.toLong()
// If expression (returns a value)valmax=if(a>b)aelseb// If statementif(x>0){println("Positive")}elseif(x<0){println("Negative")}else{println("Zero")}// When expression (enhanced switch)when(x){1->println("One")2,3->println("Two or Three")in4..10->println("Between 4 and 10")!in20..30->println("Not between 20 and 30")isString->println("Is a String of length ${x.length}")else->println("Otherwise")}// When as an expressionvalresult=when(x){0,1->"Binary digit"else->"Not a binary digit"}
Loops
// For loop with rangefor(iin1..5){println(i)// 1, 2, 3, 4, 5}// For loop with stepfor(iin1..10step2){println(i)// 1, 3, 5, 7, 9}// For loop downwardfor(iin5downTo1){println(i)// 5, 4, 3, 2, 1}// For loop with indicesfor(iinarray.indices){println(array[i])}// For loop with indexfor((index,value)inarray.withIndex()){println("Element at $index is $value")}// While loopwhile(condition){// code}// Do-while loopdo{// code}while(condition)
fungreet(name:String):String{return"Hello, $name!"}// Single-expression functionfungreet(name:String):String="Hello, $name!"// Type inference for return valuefungreet(name:String)="Hello, $name!"
Parameters
// Default parametersfungreet(name:String,greeting:String="Hello")="$greeting, $name!"// Named argumentsgreet(greeting="Hi",name="Kotlin")// Variable number of arguments (varargs)funsum(varargnumbers:Int):Int{returnnumbers.sum()}sum(1,2,3,4)// 10// Spread operator for varargsvalnumbers=intArrayOf(1,2,3)sum(*numbers)
Local Functions
funouter(){funinner(){// Has access to outer's scope}inner()}
Infix Functions
infixfunInt.plus(other:Int):Int=this+othervalresult=1plus2// Same as 1.plus(2)
// Function that takes a function as parameterfunoperation(x:Int,y:Int,op:(Int,Int)->Int):Int{returnop(x,y)}// Calling with lambdaoperation(1,2){a,b->a+b}// Function that returns a functionfunmultiplier(factor:Int):(Int)->Int{return{it*factor}}valdouble=multiplier(2)double(5)// 10
// Element accesslist[0]// First elementlist.first()// First elementlist.last()// Last elementmap["a"]// Value for key "a"// Adding elements (mutable collections)mutableList.add(4)mutableSet.add("cherry")mutableMap["c"]=3// Removing elements (mutable collections)mutableList.remove(2)mutableSet.remove("apple")mutableMap.remove("a")// Collection transformationsvaldoubled=list.map{it*2}// [2, 4, 6]valeven=list.filter{it%2==0}// [2]valsum=list.reduce{acc,i->acc+i}// 6valgrouped=list.groupBy{it%2}// {1=[1, 3], 0=[2]}valflattened=listOf(listOf(1),listOf(2,3)).flatten()// [1, 2, 3]// Checking elementslist.contains(2)// true2inlist// truelist.any{it>2}// truelist.all{it<10}// truelist.none{it<0}// truelist.count{it%2==0}// 1// Collection informationlist.size// 3list.isEmpty()// falselist.isNotEmpty()// true// Finding elementslist.find{it>2}// 3list.findLast{it<3}// 2list.indexOf(2)// 1// Sortinglist.sorted()// Natural orderlist.sortedDescending()// Reverse natural orderlist.sortedBy{it%2}// Custom order
Classes & Objects
Class Declaration
classPerson{varname:String=""varage:Int=0funintroduce(){println("I'm $name, $age years old")}}// Instantiationvalperson=Person()person.name="John"person.age=25person.introduce()
Constructors
// Primary constructorclassPerson(valname:String,varage:Int){// Init blocks run in sequence with property initializersinit{require(age>=0){"Age cannot be negative"}}}// Secondary constructorclassPerson{valname:Stringvarage:Intconstructor(name:String,age:Int){this.name=namethis.age=age}constructor(name:String):this(name,0)}
Properties
classPerson{// Backing field auto-generatedvarname:String=""get()=field.uppercase()set(value){field=value.trim()}// Custom getter (read-only property)valisAdult:Booleanget()=age>=18// Late-initialized property (no initial value needed)lateinitvarjob:String// Lazy property - initialized on first accessvalsocialSecurityNumber:Stringbylazy{calculateSSN()// Expensive operation}}
// All classes are final by defaultopenclassAnimal(valname:String){openfunmakeSound(){println("Some sound")}}classDog(name:String):Animal(name){overridefunmakeSound(){println("Woof!")}}
Abstract Classes
abstractclassShape{abstractvalarea:Doubleabstractfundraw()// Non-abstract functionfundisplay(){println("Displaying shape with area: $area")}}classCircle(valradius:Double):Shape(){overridevalarea:Doubleget()=Math.PI*radius*radiusoverridefundraw(){println("Drawing a circle")}}
Interfaces
interfaceClickable{// Abstract propertyvalclickCount:Int// Abstract methodfunonClick()// Method with default implementationfunshowOff(){println("I'm clickable!")}}interfaceFocusable{funshowOff(){println("I'm focusable!")}}// Multiple interface implementationclassButton:Clickable,Focusable{overridevalclickCount:Int=0overridefunonClick(){println("Button clicked")}// Must override conflicting methodoverridefunshowOff(){super<Clickable>.showOff()super<Focusable>.showOff()}}
Singleton (Object)
objectSingleton{valproperty="I'm a singleton"funmethod()="Only one instance exists"}// UsageSingleton.propertySingleton.method()
Companion Object
classMyClass{companionobjectFactory{funcreate():MyClass=MyClass()}}// Usage (like static methods in Java)valinstance=MyClass.create()
Enum Classes
enumclassDirection{NORTH,EAST,SOUTH,WEST}// Enum with properties and methodsenumclassColor(valrgb:Int){RED(0xFF0000),GREEN(0x00FF00),BLUE(0x0000FF);funcontainsRed():Boolean=(rgband0xFF0000!=0)}
Sealed Classes
// Restricted class hierarchysealedclassResult{classSuccess(valdata:Any):Result()classError(valmessage:String):Result()objectLoading:Result()}// Ideal for use with whenfunhandleResult(result:Result)=when(result){isResult.Success->println("Success: ${result.data}")isResult.Error->println("Error: ${result.message}")isResult.Loading->println("Loading...")// No else branch needed as all subclasses are covered}
// Non-nullable typevarnonNull:String="value"nonNull=null// Compilation error// Nullable typevarnullable:String?="value"nullable=null// OK
Safe Calls
// Returns null if user is nullvallength=user?.name?.length// Chain of safe callsvalcity=user?.address?.city// Safe call with letuser?.let{println("User name is ${it.name}")}
Elvis Operator
// Default value if nullvallength=str?.length?:0// Throw exception if nullvalname=user?.name?:throwIllegalArgumentException("User must have a name")
Not-null Assertion
// Throws NullPointerException if nullvallength=str!!.length
Safe Casts
// Returns null if cast failsvalstr:String?=valueas?String
Platform Types
// Types coming from Java are treated as platform types (neither nullable nor non-null)// import java.util.Date// fun getDate(): Date = Date() // Java method// val date: Date = getDate() // Treated as non-nullable// val nullableDate: Date? = getDate() // Treated as nullable
// launch - fire and forgetlaunch{// Coroutine code}// async - returns a resultvaldeferred=async{// Coroutine code that returns a value"Result"}valresult=deferred.await()// runBlocking - bridges blocking and non-blocking worldsrunBlocking{// Coroutine code}// coroutineScope - creates a new scope and waits for all childrencoroutineScope{launch{delay(1000)}launch{delay(2000)}}// Waits for both launches to complete
Coroutine Context & Dispatchers
// Dispatcherslaunch(Dispatchers.Default){/* CPU-intensive work */}launch(Dispatchers.IO){/* I/O operations */}launch(Dispatchers.Main){/* UI updates */}// Named coroutines for debugginglaunch(CoroutineName("my-coroutine")){/* ... */}// Combined contextlaunch(Dispatchers.IO+CoroutineName("io-work")){/* ... */}// Job for cancellation controlvaljob=launch{/* ... */}job.cancel()job.join()// Wait for completion
Exception Handling
valhandler=CoroutineExceptionHandler{_,exception->println("Caught $exception")}valjob=GlobalScope.launch(handler){throwRuntimeException("Oops")}// supervisorScope for independent failure of childrensupervisorScope{valjob1=launch{/* may fail */}valjob2=launch{/* continues even if job1 fails */}}
Flow
// Creating a flowvalflow=flow{for(iin1..3){delay(100)emit(i)}}// Collecting a flowflow.collect{value->println(value)}// Flow operatorsflow.map{it*2}.filter{it>0}.take(2).collect{println(it)}
Extension Functions
Basic Extension Function
// Add a method to String classfunString.addExclamation():String{returnthis+"!"}// Usagevalexcited="Hello".addExclamation()// "Hello!"
// Full syntaxvalsum={a:Int,b:Int->a+b}// Type inferencevalmultiply:(Int,Int)->Int={a,b->a*b}// Calling a lambdasum(1,2)// 3// Lambda with receivervalgreet:String.()->String={"Hello, $this!"}"Kotlin".greet()// "Hello, Kotlin!"
Function References
// Reference to a functionfunisOdd(x:Int)=x%2!=0valnumbers=listOf(1,2,3)numbers.filter(::isOdd)// [1, 3]// Reference to a constructorclassPerson(valname:String)valcreatePerson=::Personvalperson=createPerson("John")// Reference to an instance methodvalpredicate=String::isNotEmpty
Higher-Order Functions
// Standard library examplesvalnumbers=listOf(1,2,3,4)numbers.filter{it%2==0}// [2, 4]numbers.map{it*it}// [1, 4, 9, 16]numbers.forEach{println(it)}// Prints each numbernumbers.fold(0){acc,n->acc+n}// 10
Sequences
// Lazy evaluation (more efficient for chained operations)valresult=sequenceOf(1,2,3,4).filter{println("Filter: $it");it%2==0}.map{println("Map: $it");it*it}.first()// Only processes elements until first result// Generate sequencesvalfibonacci=sequence{vara=0varb=1while(true){yield(a)valnext=a+ba=bb=next}}fibonacci.take(5).toList()// [0, 1, 1, 2, 3]
Scope Functions
// let - object as it, returns lambda resultvallength=str?.let{println("Processing '$it'")it.length}// run - object as this, returns lambda resultvalupperCase=str.run{println("Processing '$this'")uppercase()}// with - object as this, returns lambda result (extension-like)valresult=with(str){println("Processing '$this'")length*2}// apply - object as this, returns the object (builder-like)valperson=Person().apply{name="John"age=30}// also - object as it, returns the object (side effects)valnumbers=mutableListOf(1,2,3).also{println("List: $it")}.also{it.add(4)}
Top comments (0)