View Source

In [Kotlin], everything is an object in the sense that one can call member functions and properties on any variable. Some types are built-in, because their implementation is optimized, but for the used they look like ordinary classes. In this section we describe most of these types: [numbers|#Numbers], [characters|#Characters], [booleans|#Booleans] and [arrays|#Arrays].

h3. Numbers

[Kotlin] handles numbers in a way close to *Java*, but not exactly the same. For example, there are no _implicit widening conversions_ or numbers, and literals are slightly different in some cases.

[Kotlin] provides the following built-in types representing numbers (this is close to *Java*):
|| Type || Bitwidth ||
| Double | 64 |
| Float | 32 |
| Long | 64 |
| Int | 32 |
| Short | 16 |
| Byte | 8 |

Note that [characters|#Characters] are not numbers in [Kotlin].

h4. Representation

On the *Java* platform, numbers are physically stored as JVM primitive types, unless we need a [nullable|Null-safety] number reference (e.g. {{Int?}}) or generics are involved. In the latter cases numbers are _boxed_.

*Note* that boxing of numbers does not preserve [identity|Basic operations]:
val a : Int = 10000
print(a identityEquals a) // Prints 'true'
val boxedA : Int? = a
val anotherBoxedA : Int? = a
print(boxedA identityEquals anotherBoxedA) // !!!Prints 'false'!!!
On the other hand, it preserves [equality|Expressions#Equality checks]:
val a : Int = 10000
print(a == a) // Prints 'true'
val boxedA : Int? = a
val anotherBoxedA : Int? = a
print(boxedA == anotherBoxedA) // Prints 'true'

h4. Explicit conversions

Due to different representations, smaller types are not _subtypes_ of bigger ones.
If they were, we would have troubles of the following sort:
// Hypothetical code, does not actually compile:
val a : Int? = 1 // A boxed Int (java.lang.Integer)
val b : Long? = a // implicit conversion yields a boxed Long (java.lang.Long)
print(a == b) // Surprise! This prints "false" as Long's equals() check for other part to be Long as well
So not only identity, but even equality would have been lost silently all over the place.

As a consequence, smaller types are *NOT* implicitly converted to bigger types. This means that one cannot assign a value of type {{Byte}} to an {{Integer}} variable without an explicit conversion:
val b : Byte = 1 // OK, literals are checked statically
val i : Int = <error desc="Incompatible types: Byte cannot be assigned to a variable of type Int. Use the explicit conversion '.toInt()'">b</error> // ERROR
One can use *explicit conversions* to widen numbers:
val i : Int = b.toInt() // OK: explicitly widened

Every number type supports the following conversions:
* {{toByte() : Byte}}
* {{toShort() : Short}}
* {{toInt() : Int}}
* {{toLong() : Long}}
* {{toFloat() : Float}}
* {{toDouble() : Double}}
* {{toChar() : Char}}

Absence of implicit conversions is rarely noticeable because one can use literals almost freely cause the type is inferred from the context, and arithmetical operations are _overloaded_ for appropriate conversions, for example
val l = 1.toLong() + 3 // Long + Int => Long

h4. Literals

All the integer literals are written in the same way:
* Decimals: {{123}}, {{123L}}, {{123.5}}, {{123.5e10}}, {{123.5f}}
* Hexadecimals: {{0x0F}}
* Binaries: {{0b00001011}}

*NOTE*: Octal literals are not supported.

You can only use a capital "L" for suffixing {{Long}} values (little "l" looks too much like "1" in many fonts), both "F" and "f" are allowed for {{Float}}'s. Alternatively, one could use explicit conversions to specify a type for a literal:
val list = list(1.toLong(), 100000000000, 2.toLong())

h4. Operations

[Kotlin] supports the standard set of arithmetical operations over numbers, which are declared as members of appropriate classes (but the compiler optimizes the calls down to the corresponding instructions). See [Operator overloading|Functions#Operator overloading].

As of _bitwise_ operations, there're no special characters for them, but just named functions that can be called in [infix form|Functions#Infix calls], for example:
val x = (1 shl 2) and 0x000FF000
Here is the complete list of bitwise operations (available for {{Int}} and {{Long}} only):
* {{shl(bits)}} -- signed shift left (*Java*'s {{<<}})
* {{shr(bits)}} -- signed shift right (*Java*'s {{>>}})
* {{ushr(bits)}} -- unsigned shift right (*Java*'s {{>>>}})
* {{and(bits)}} -- bitwise {{and}}
* {{or(bits)}} -- bitwise {{or}}
* {{xor(bits)}} -- bitwise {{xor}}
* {{inv()}} -- bitwise inversion

h2. Characters

Characters are represented by the type {{Char}}. They are can not be treated directly as numbers:
fun check(c : Char) {
if (c <error desc="A value of type Char cannot be equal to a value of type Int">==</error> 1) { // ERROR: incompatible types
// ...
Character literals go in single quotes: {{'1'}}, {{'\n'}}, {{'\uFF00'}}.
One can explicitly _convert_ a character to an {{Int}} number:
fun decimalDigitValue(c : Char) : Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // Explicit conversions to numbers

Like numbers, characters are *boxed* when a nullable reference is needed. Identity is not preserved by the boxing operation.

h2. Booleans

The type {{Boolean}} represents booleans, and has two values: {{true}} and {{false}}.

Booleans are boxed if a nullable reference is needed.

Built-in operations on booleans include
* {{\|\|}} -- lazy disjunction
* {{&&}} -- lazy conjunction

h3. Arrays

Arrays in [Kotlin] are represented by the {{Array}} class, that has {{get}} and {{set}} functions (that turn into {{\[\]}} by [operator overloading conventions|Operator overloading]), and {{size}}, along with a few other useful member functions:
class Array<T>(val size : Int, init : (Int) -> T) {
fun get(index : Int) : T
fun set(index : Int, value : T) : Unit

fun iterator() : Iterator<T>

val indices : IntRange

To create an array one can call its [constructor|Classes and Inheritance#Classes and Primary constructors] providing the array size and a [function|Function literals] that knows how to initialize elements of the array:
val asc = Array<Int>(5, {i -> i * i}) // Creates an array [0, 1, 4, 9, 16]
Or, alternatively, one can use a library function {{array()}} and pass the item values to it, so that {{array(1, 2, 3)}} creates an array {{\[1, 2, 3\]}}.

As we said above, the {{\[\]}} operation stands for calls to member functions {{get()}} and {{set()}}. When compiling to JVM byte codes, the compiler optimizes access to arrays so that there's no overhead introduced, and all operations work exactly like in *Java*:
val array = array(1, 2, 3, 4)
array[x] = array[x] * 2 // no actual calls to get() and set() generated
for (x in array) // no iterator created
Even when we navigate with an index, it does not introduce any overhead:
for (i in array.indices) // no iterator created
array[i] += 2
Finally, *in*\-checks have no overhead either
if (i in array.indices) { // same as (i >= 0 && i < array.size)

*Note*: arrays are [invariant|Java interoperability#Arrays]. For the best performance on the JVM use [specialized array classes|Java interoperability#Arrays].

h3. What's next

* [Strings]