Basic Syntax
Defining packages
Package specification should be at the top of the source file:
package my.demo
import java.util.*
// ...
It is not required to match directories and packages: source files can be placed arbitrarily in the file system.
See Packages.
Defining functions
Function having two Int
parameters with Int
return type:
fun sum(a: Int, b: Int): Int {
return a + b
}
Function with an expression body and inferred return type:
fun sum(a: Int, b: Int) = a + b
Function returning no meaningful value:
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
Unit
return type can be omitted:
fun printSum(a: Int, b: Int) {
print(a + b)
}
See Functions.
Defining local variables
Assign-once (read-only) local variable:
val a: Int = 1
val b = 1 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 1 // definite assignment
Mutable variable:
var x = 5 // `Int` type is inferred
x += 1
See also Properties And Fields.
Comments
Just like Java and JavaScript, Kotlin supports end-of-line and block comments.
// This is an end-of-line comment
/* This is a block comment
on multiple lines. */
Unlike Java, block comments in Kotlin can be nested.
See Documenting Kotlin Code for information on the documentation comment syntax.
Using string templates
fun main(args: Array<String>) {
if (args.size == 0) return
print("First argument: ${args[0]}")
}
See String templates.
Using conditional expressions
fun max(a: Int, b: Int): Int {
if (a > b)
return a
else
return b
}
Using if{: .keyword } as an expression:
fun max(a: Int, b: Int) = if (a > b) a else b
See if{: .keyword }-expressions.
Using nullable values and checking for null{: .keyword }
A reference must be explicitly marked as nullable when null{: .keyword } value is possible.
Return null{: .keyword } if str
does not hold an integer:
fun parseInt(str: String): Int? {
// ...
}
Use a function returning nullable value:
fun main(args: Array<String>) {
if (args.size < 2) {
print("Two integers expected")
return
}
val x = parseInt(args[0])
val y = parseInt(args[1])
// Using `x * y` yields error because they may hold nulls.
if (x != null && y != null) {
// x and y are automatically cast to non-nullable after null check
print(x * y)
}
}
or
// ...
if (x == null) {
print("Wrong number format in '${args[0]}'")
return
}
if (y == null) {
print("Wrong number format in '${args[1]}'")
return
}
// x and y are automatically cast to non-nullable after null check
print(x * y)
See Null-safety.
Using type checks and automatic casts
The is{: .keyword } operator checks if an expression is an instance of a type. If an immutable local variable or property is checked for a specific type, there's no need to cast it explicitly:
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// `obj` is automatically cast to `String` in this branch
return obj.length
}
// `obj` is still of type `Any` outside of the type-checked branch
return null
}
or
fun getStringLength(obj: Any): Int? {
if (obj !is String)
return null
// `obj` is automatically cast to `String` in this branch
return obj.length
}
or even
fun getStringLength(obj: Any): Int? {
// `obj` is automatically cast to `String` on the right-hand side of `&&`
if (obj is String && obj.length > 0)
return obj.length
return null
}
See Classes and Type casts.
Using a for
loop
fun main(args: Array<String>) {
for (arg in args)
print(arg)
}
or
for (i in args.indices)
print(args[i])
See for loop.
Using a while
loop
fun main(args: Array<String>) {
var i = 0
while (i < args.size)
print(args[i++])
}
See while loop.
Using when
expression
fun cases(obj: Any) {
when (obj) {
1 -> print("One")
"Hello" -> print("Greeting")
is Long -> print("Long")
!is String -> print("Not a string")
else -> print("Unknown")
}
}
See when expression.
Using ranges
Check if a number is within a range using in{: .keyword } operator:
if (x in 1..y-1)
print("OK")
Check if a number is out of range:
if (x !in 0..array.lastIndex)
print("Out")
Iterating over a range:
for (x in 1..5)
print(x)
See Ranges.
Using collections
Iterating over a collection:
for (name in names)
println(name)
Checking if a collection contains an object using in{: .keyword } operator:
if (text in names) // names.contains(text) is called
print("Yes")
Using lambda expressions to filter and map collections:
names
.filter { it.startsWith("A") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { print(it) }