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, characters, booleans and arrays.
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):
On the Java platform, numbers are physically stored as JVM primitive types, unless we need a nullable 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:
On the other hand, it preserves equality:
Due to different representations, smaller types are not subtypes of bigger ones.
If they were, we would have troubles of the following sort:
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:
One can use explicit conversions to widen numbers:
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
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:
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.
As of bitwise operations, there're no special characters for them, but just named functions that can be called in infix form, for example:
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
Characters are represented by the type Char. They are can not be treated directly as numbers:
Character literals go in single quotes: '1', '\n', '\uFF00'.
One can explicitly convert a character to an Int number:
Like numbers, characters are boxed when a nullable reference is needed. Identity is not preserved by the boxing operation.
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
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:
Even when we navigate with an index, it does not introduce any overhead:
Finally, in-checks have no overhead either