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)}
Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!
Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.
A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!
On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.
Top comments (0)