Operators

Kotlin provides all standard operators to build expression.

Unlike Java, some statements can be used as operator that returns last value:

  • if else
  • when
  • try catch

Most operators are implemented as methods of the corresponding types. Thus, you can use operators in infix notation as usual or as methods.

// val orResult = num1.or(num2)
val orResult = num1 or num2 

Kotlin allows you to provide custom implementations for the predefined set of operators using overloading.

To implement an operator, provide a member function or an extension function with a specific name and the operator modifier for the corresponding type.

unary operators

+, -, ++ (increases value by 1), -- (decreases value by 1), ! (invert boolean value)

val x = 1
val y = 1
val b = true
println(++x)
println(y++)
println(!b)

The postfix “++” operator, first returns the current value and then increases the value.

The prefix “++” operator, first increases the value and then returns the newly incremented value.

Similarly for "--" operator.

To overload unary operators use following methods:

  • unaryPlus - for unary +
  • unaryMinus - for unary -
  • not - for !
  • inc - for ++
  • dec - for --

arithmetic operators

+, -, *, /, % (remainder of division), .. (range from a to b)

The + operator is also used for the concatenation of String values.

To overload arithmetic operators use following methods:

  • plus - for binary +
  • minus - for binary -
  • times - for *
  • div - for /
  • rem - for % (remainder of division)
  • rangeTo - for .. (range from a to b)
var z = x + y // or x.plus(y)
var rangeAB = a..b // or a.rangeTo(b)

assignment operators

=, +=, -=, *=, /=, %=

To overload assignment operators use following methods:

  • Kotlin does not support overriding the = operator
  • plusAssign - for binary +=
  • minusAssign - for binary -=
  • timesAssign - for *=
  • divAssign - for /=
  • remAssign - for %=

Assignments are not expressions in Kotlin, i.e. don't generate result.

comparison operators

  • <
  • >
  • <= - less than or equal to
  • >= - greater than or equal to
  • != - not equal
  • == - equal

To overload comparison operators use following methods:

  • compareTo - for <, >, <=, >=
  • equals - for ==, !=

The identity equals operator === checks whether the operands point to the same object. Operator can’t be overloaded.

Similarly operator !== checks whether the operands point to the different objects. Operator can’t be overloaded.

logic operators

  • && logical and, returns true if both statements are true
  • || logical or, returns true if one of the statements is true
  • ! - logical not, inverts boolean value

You can not overload || and && operators.

bitwise operators

Bitwise operators are used on following types:

  • Int
  • Long
val orResult = num1 or num2 // bitwise "or"
val andResult = num1 and num2 // bitwise "and"
val andResult = num1 xor num2 // bitwise "xor"

val orResult1 = num1.or(num2) // perform bitwise "or" via method

To overload bitwise operators use following methods:

  • or
  • and
  • xor
  • inv - bit inversion
  • shl - shift bits into the low-order positions (i.e. left shift)
  • shr - shift bits into the high-order positions, filling the leftmost bits with copies of the sign bit (i.e. right shift)
  • ushr - shift bits into the high-order positions, filling the leftmost bits with zeros.

null safety operators

Use ?: (Elvis operator) to check null value.


var l: Int = if (b != null) b.length else -1

// same as

l = b?.length ?: -1

Use ?. operator to specify that value can be null. Safe calls are useful in chains.

val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // Unnecessary safe call

// Returns null if any of the properties in it is null.
var name = bob?.department?.head?.name

Use the !! operator to indicate that a value cannot be null.

val l = b!!.length

other operators

Use the get()/set() method to override the [] index operator. By default [] operator is implemented for arrays, lists and maps.

var item1 = a[i] // same as: a.get(i)
var item2 = b[i,j] // c b.get(i, j)

a[i] = v // same as: a.set(i, v)
b[i, j] = v // same as: b.set(i,j, v)

// similarly for n arguments

Use the contains() method to override the in operator. By default [] operator is implemented for collections.

a in b // same as: b.contains(a)
a !in b // same as: !b.contains(a) 

Use the invoke() method to override the () operator.

a() // same as: a.invoke()
a(i) // same as: a.invoke(i)

// similarly for n arguments

operator overloading

To implement an operator, provide a member function or an extension function with a specific name for the corresponding type.

Mark the corresponding function with the operator modifier.

data class Point(val x: Int, val y: Int)

operator fun Point.unaryMinus() = Point(-x, -y)

val point = Point(10, 20)

fun main() {
   println(-point)  // prints "Point(x=-10, y=-20)"
}

&&, ||, ?:, ===, !== operators cannot be overloaded.