Kotlin Syntax
by:
Department of Computing and Mathematics
http://www.wit.ie/
Kotlin Syntax
Sources: http://kotlinlang.org/docs/reference/basic-syntax.html
http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/
Agenda
• Basic Types
• Local Variables (val & var)
• Functions
• Control Flow (if, when, for, while)
• Strings & String Templates
• Ranges (and the in operator)
• Type Checks & Casts
• Null Safety
• Comments
Basic Types
Numbers, characters and booleans.
Basic Types
In Kotlin, everything is an
object in the sense that we
can call member functions
and properties on any
variable.
Basic Types - Numbers
Basic Types - Numbers
val doubleNumber: Double = 100.45
val floatNumber: Float = 100.45f
val longNumber: Long = 100
val intNumber: Int = 100
val shortNumber: Short = 100
val byteNumber: Byte = 100
Explicitly defining a
numeric type
Basic Types - Numbers
val doubleNumber = 100.45
val floatNumber = 100.45f
Type val longNumber = 100L
inference val intNumber = 100
val shortNumber = 100
val byteNumber = 100
Basic Types - Numbers
val doubleNumber = 100.45
val floatNumber = 100.45f
Type val longNumber = 100L
inference val intNumber = 100
val shortNumber = 100
val byteNumber = 100
println("doubleNumber type is: " + doubleNumber.javaClass)
println("floatNumber type is: " + floatNumber.javaClass)
println("longNumber type is: " + longNumber.javaClass)
println("intNumber type is: " + intNumber.javaClass)
println("shortNumber type is: " + shortNumber.javaClass)
println("byteNumber type is: " + byteNumber.javaClass)
Basic Types - Numbers
val oneMillion = 1_000_000
val threeThousand = 3_000
val creditCardNumber = 1234_4321_5678_8765
fun main(args : Array<String>)
{
println("" + oneMillion + " - the type is: " + oneMillion.javaClass)
println("" + threeThousand + " - the type is: " + threeThousand.javaClass)
println("" + creditCardNumber + " - the type is: " + creditCardNumber.javaClass)
}
You can use
underscores to
make number
constants more
readable.
Basic Types – Numbers: Explicit Conversions
In Kotlin, there are no implicit widening conversions for numbers i.e.
smaller types (e.g. Byte) are not subtypes of bigger ones (e.g. Int)
smaller types are NOT implicitly converted to bigger types.
Basic Types – Numbers: Explicit Conversions
In Kotlin, there are no implicit widening conversions for numbers i.e.
smaller types (e.g. Byte) are not subtypes of bigger ones (e.g. Int)
smaller types are NOT implicitly converted to bigger types.
val byteNumber: Byte = 10 //static type check: OK
val intNumber: Int = byteNumber //syntax error
BUT, we can use explicit conversions to widen numbers
val byteNumber: Byte = 10 //static type check: OK
val intNumber: Int = byteNumber.toInt() //OK
Basic Types – Numbers: Explicit Conversions
Every number type supports the following conversions:
• toByte(): Byte
• toShort(): Short
• toInt(): Int
• toLong(): Long
• toFloat(): Float
• toDouble(): Double
• toChar(): Char
//Explicit Conversion
val intNumber: Int = byteNumber.toInt()
val floatNumber: Float = byteNumber.toFloat()
Basic Types – Characters
val aChar = 'a'
val bChar: Char = 'b'
fun main(args : Array<String>)
{
println("" + aChar + " - the type is: " + aChar.javaClass)
println("" + bChar + " - the type is: " + bChar.javaClass)
}
Basic Types – Booleans
val aFlag = true
val bFlag: Boolean = false
fun main(args : Array<String>)
{
println("" + aFlag + " - the type is: " + aFlag.javaClass)
println("" + bFlag + " - the type is: " + bFlag.javaClass)
}
Basic Types – Escape Characters
Special characters can be escaped using a backslash:
\t \b \n \r \’ \“ \\ \$
val aFlag= true
val bFlag: Boolean = false
fun main(args : Array<String>)
{
println("" + aFlag + " - the type is: \n\t\t" + aFlag.javaClass)
println("" + bFlag + " - the type is: \n\t\t" + bFlag.javaClass)
}
Local Variables
val (read-only) and var (mutable)
Local Variables – val (read-only)
Local Variables – val (read-only)
Local Variables – var (mutable)
Local Variables – var (mutable)
Functions
Parameters, return types, expression body, inferred return type
Functions – parameters and return types
Functions – expression body, inferred return type
Function “sum” with an expression
body and inferred return type
fun sum(a: Int, b: Int) = a + b
fun main(args: Array<String>) {
println("sum of 19 and 23 is ${sum(19, 23)}")
println("sum of 19 and 23 is " + sum(19, 23))
}
Functions – no return data
Control Flow
if, when, for, while
Control Flow – if
The traditional
way to write if’s
Control Flow – if
The traditional
way to write if’s
HOWEVER….in Kotlin, if is an expression, i.e. it returns a
value. Therefore there is no ternary operator (condition ?
then : else), because ordinary if works fine in this role.
Control Flow – if
Using if as an
expression
Control Flow – if
Some examples
without using
functions.
The first two
examples use if as a
statement.
The last example
uses if as an
expression.
Control Flow – if
if branches can also be blocks.
The last expression is the value of a block:
val a = 10;
val b = 5;
val max = if (a > b) {
print ("Choose a")
a
}
else {
print ("Choose b")
b
}
Control Flow – if
if branches can also be blocks.
The last expression is the value of a block:
val a = 10;
val b = 5;
val max = if (a > b) {
When if is used as
print ("Choose a") an expression, the
a else part is
} mandatory.
else {
print ("Choose b")
b
}
Replaces
Control Flow – when
switch in
val x = 10; Java
when (x){
1 -> print("x is 1")
2 -> print("x is 2")
in 3..10 -> print ("x is between 3 and 10")
}
Control Flow – when
Control Flow – when
Branch conditions may be
combined with a comma.
We can use arbitrary
expressions (not only constants)
as branch conditions.
We can also check a value
for being in or !in a range
or a collection.
Control Flow – when
val x = "I am a String"
val contains = when (x){ Another possibility is
is String -> x.contains("I am a") to check that a value
else -> false is or !is of a particular
}
type.
println(contains)
Control Flow – when
when can also be used as a replacement for an if-else if chain.
If no argument is supplied, the branch conditions are simply boolean
expressions, and a branch is executed when its condition is true.
val aString = "I am a String"
when {
aString.equals("I am a String") -> println("Equal");
else -> println("Not Equal")
}
Control Flow – when
Control Flow – for
The for loop iterates through anything that provides an
iterator. It is similar to the for-each loop in Java.
Control Flow – for
If you want to iterate through
an array or a list with an index,
you can do it this way:
Control Flow – for
Alternatively, you can use the
withIndex library function:
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for ((index, value) in items.withIndex()) {
println("the element at ${index} is ${value}")
}
}
Control Flow – while
The while and do-while work as usual:
Note: Kotlin also supports traditional break and continue operators in loops.
Control Flow – while
val items = listOf("apple", "banana", "kiwi")
var index = 0
while (index < items.size){
println("item at $index is ${items[index]}")
index++
}
Strings and String Templates
Escaped strings, raw strings, literals, templates
Strings
• Strings are represented by the type String.
• Strings are immutable.
• Elements of a string are characters that can be accessed by the
indexing operation: s[i].
• A string can be iterated over with a for-loop:
String Literals
• Kotlin has two types of string literals:
escaped strings that may have escaped characters in them and
raw strings that can contain newlines and arbitrary text.
String Literals
• Kotlin has two types of string literals:
escaped strings that may have escaped characters in them and
raw strings that can contain newlines and arbitrary text.
An escaped string is very much like
a Java string
A raw string is delimited by a triple
quote (“””), contains no escaping
and can contain new lines and any
other characters.
String Literals
You can remove
leading whitespace
with trimMargin()
String Literals
By default | is used as margin prefix, but you can choose
another character and pass it as a parameter like
trimMargin(">").
val text = """
> Tell me and I forget.
> Teach me and I remember.
Note the impact of the
> Involve me and I learn. two spaces we put
> (Benjamin Franlkin) between > and the text
""".trimMargin(">")
print(text)
String Templates
• Strings may contain template expressions, i.e. 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 simple name:
• or an arbitrary expression in curly braces:
String Templates
Templates are supported both inside raw strings and inside escaped
strings.
val anInt = 10
val aString = "Value of anInt is ${anInt}\n"
val text = """
> Tell me and I forget.
> Teach me and I remember.
> Involve me and I learn.
> (Benjamin Franlkin)
""".trimMargin(">")
print(aString)
print(text)
String Templates
s1
“a is 1”
Ranges
The in operator
Range
Check if a number
is within a range
using in operator:
Check if a
number is
out of range:
Range
Iterating over
a range:
Iterating over
a progression:
Type Checks & Casts
is and !is operators
fun main(args: Array<String>) {
val aString = "I am a String"
if (aString is String) {
println("String length is: ${aString.length}")
}
if (aString !is String) { // same as !(aString is String)
print("Not a String")
}
else {
println("String length is: ${aString.length}")
}
}
Smart Casts (an example using if)
fun main(args: Array<String>) {
demo ("I am a String")
demo (12)
}
fun demo(x: Any) {
if (x is String) {
println(x.length) // x is automatically cast to String
}
else{
println(x.javaClass)
}
}
Smart Casts (an example using when)
fun main(args: Array<String>) {
demo (12)
demo ("I am a String")
demo (intArrayOf(1,2,3,4))
}
fun demo(x: Any) {
when (x) {
is Int -> println(x + 1)
is String -> println(x.length + 1)
is IntArray -> println(x.sum())
}
}
Null
Using nullable values and checking for null
Null Safety
In Kotlin, the type system distinguishes
between references that can hold
null (nullable references)
and those that
cannot (non-null references).
The Kotlin compiler makes sure you don’t, by accident,
operate on a variable that is null.
Null Safety – a non-null reference
A regular variable of var a: String = "abc"
type String can not
a = null // syntax error
hold null
Calling a method /
accessing a property
on variable a, is
guaranteed not to val l = a.length
cause an
NullPointerException
Null Safety – a nullable reference
To allow nulls, we
can declare a variable var b: String? = "abc"
as nullable string, b = null // ok
written String?
val l = b.length // syntax error: variable
//'b' can be null
// …many ways around this…
Null Safety – a nullable reference
To allow nulls, we
can declare a variable var b: String? = "abc"
as nullable string, b = null // ok
written String?
Option 1: you can explicitly check if b is null,
and handle the two options separately:
val l = if (b != null) b.length else -1
Null Safety – a nullable reference
To allow nulls, we
can declare a variable var b: String? = "abc"
as nullable string, b = null // ok
written String?
Option 2: you can use the safe call operator ?.
This returns b.length if b is not null, and null otherwise.
b?.length
:
Null Safety – a nullable reference
To allow nulls, we
can declare a variable var b: String? = "abc"
as nullable string, b = null // ok
written String?
Option 3: you can use the !! Operator. This force a
call to our method and will return a non-null value
of b or throw an NPE if b is null. Use sparingly!
val l = b!!.length
:
Null Safety – The Elvis Operator, ?:
When we have a nullable reference r, we can say:
"if r is not null, use it, otherwise use some non-null value x"
val l: Int = if (b != null) b.length else -1
:
Null Safety – The Elvis Operator, ?:
When we have a nullable reference r, we can say:
"if r is not null, use it, otherwise use some non-null value x"
val l: Int = if (b != null) b.length else -1
Along with the complete if-expression, this can be expressed
with the Elvis operator, written ?:
val l = b?.length ?: -1
If the expression to the left of ?: is not null, the elvis operator
returns it, otherwise it returns the expression to the right.
Nullable – nullable returns
A reference must be explicitly marked as
nullable (i.e. ?) when null value is possible.
Return null if the return value
does not hold an integer:
Comments
Single line, block, KDoc
Comments – single line and block comments
Comments – KDoc (equivalent to JavaDoc)
Comments – KDoc
Block tags Currently supported KDoc block tags
@param <name> Documents a value parameter of a function or a type parameter of a class, property or
function.
@return Documents the return value of a function.
@constructor Documents the primary constructor of a class.
@receiver Documents the receiver of an extension function.
@property <name> Documents the property of a class which has the specified name.
@throws <class>, Documents an exception which can be thrown by a method.
@exception <class>
@sample <identifier> Embeds the body of the function with the specified qualified name into the
documentation for the current element, in order to show an example of how the
element could be used.
@see <identifier> Adds a link to the specified class or method to the See Also block of the documentation.
@author Specifies the author of the element being documented.
@since Specifies the version of the software in which the element being documented was
introduced.
@suppress Excludes the element from the generated documentation. Can be used for elements
which are not part of the official API of a module but still have to be visible externally.
For more info: http://kotlinlang.org/docs/reference/kotlin-doc.html
Except where otherwise noted, this content is
licensed under a Creative Commons
Attribution-NonCommercial 3.0 License.
For more information, please see
http://creativecommons.org/licenses/by-
nc/3.0/