December Code

Kotlin data types interview questions, with answers

Kotlin looks like a lighter Java, and its basic types are where the differences start: no primitive types in the language, no implicit widening between numbers, read-only variables with val, string templates instead of concatenation, and special types such as Unit and Nothing that Java has no equivalent for. Android and backend interviews use these questions to check that a candidate writes Kotlin, not Java with Kotlin syntax.

The answers below cover the built-in types, val and var, conversions, strings, the special types and ranges, with code compiled with kotlinc 2.3 and run on the JVM. Then take the free Kotlin diagnostic — ten questions across every Kotlin topic in the bank — to see which of these you can explain but not yet predict.

The questions, with answers

  1. 1.What are Kotlin's basic data types?

    In short: Byte, Short, Int and Long for integers, Float and Double for decimals, Boolean, Char and String; all are objects in the language and compile to JVM primitives where possible.

    Kotlin has no separate primitive types: Int, Double and the rest are classes with methods, yet the compiler stores them as JVM primitives such as int and double wherever it can, boxing them only for nullable types and generics. Integer literals are Int unless they do not fit, in which case they become Long, which is why 3_000_000_000 below is a Long; the underscores are only for readability. Char is a UTF-16 code unit and is not a number, so its code is read with c.code. Unsigned types, UInt and ULong, exist for bit manipulation, and String is an immutable sequence of chars.

    val big = 3_000_000_000
    println(big::class.simpleName)
    // Long
    val c: Char = 'k'
    println(c.code)
    // 107
  2. 2.What is the difference between val and var in Kotlin?

    In short: val declares a read-only variable that cannot be reassigned after initialisation; var declares one that can be.

    var tries = 1 can later be assigned a new value, as tries += 2 does below. val limit = 5 is assigned exactly once, and any reassignment is a compile error, like a final variable in Java. Kotlin style prefers val by default and var only where a value really changes, which makes code easier to follow and safe to share. val restricts the variable, not the object it refers to: a val holding a mutable list still lets the list change. Properties follow the same rule, with a val property having only a getter and a var property a getter and a setter.

    var tries = 1
    tries += 2
    val limit = 5
    println("$tries/$limit")
    // 3/5
  3. 3.How do numeric conversions work in Kotlin?

    In short: Kotlin never widens numbers implicitly between variables; you convert explicitly with toLong(), toDouble() and similar functions, while arithmetic operators accept mixed types.

    In Java an int silently widens to a long; in Kotlin, assigning an Int variable to a Long is a compile error, so conversions are always written: i.toLong(), x.toInt(), n.toDouble(). Converting a Double to an Int truncates toward zero, and converting a large Long to an Int keeps only the low bits, so the explicit call is also a reminder to check the range. Literals are the exception: val l: Long = 10 compiles, because the literal takes the expected type. Arithmetic operators are overloaded for mixed operands, so an Int divided by a Double, as below, gives a Double without any conversion.

    val i = 10
    val l: Long = i.toLong()
    val d = i / 4.0
    println("$l $d")
    // 10 2.5
  4. 4.What are string templates in Kotlin?

    In short: A $name or ${expression} inside a string literal is replaced by the value's text, replacing concatenation.

    String literals can embed values directly: $name inserts a variable, and ${...} inserts any expression, such as ${n * 2} below or ${user.name}. Each value is converted with toString, so objects print with their own toString implementation. Templates compile to efficient string building, so they are the idiomatic choice over +, which still works but is harder to read. A literal dollar sign is written \$ in an ordinary string, or ${'$'} in a raw string. Templates work in raw triple-quoted strings too, which is why they suit multi-line messages and generated text.

    val name = "Ria"
    val n = 3
    println("$name: ${n * 2} pts")
    // Ria: 6 pts
  5. 5.What are raw strings in Kotlin?

    In short: A triple-quoted string keeps newlines and backslashes exactly as written, and trimIndent removes the common indentation of its lines.

    An ordinary string needs escapes such as \n for a newline and \\ for a backslash. A raw string, written between triple quotes, contains exactly what is typed, including line breaks and backslashes, which makes it convenient for regular expressions, JSON and multi-line text. Because the source code is indented, the text would carry that indentation, so raw strings are usually followed by trimIndent(), which removes the smallest common indentation and the first and last blank lines, or by trimMargin(), which strips everything up to a | marker on each line. The poem below becomes two lines with no leading spaces.

    val poem = """
        roses
        violets
    """.trimIndent()
    println(poem.lines())
    // [roses, violets]
  6. 6.What are Any, Unit and Nothing in Kotlin?

    In short: Any is the root of all non-null types, Unit is the type of functions that return no meaningful value, and Nothing is the type of expressions that never complete.

    Every Kotlin class extends Any, which provides equals, hashCode and toString; Any? additionally admits null. Unit plays the role of Java's void, but it is a real type with a single value, so a function returning nothing useful returns Unit, and println(x) below evaluates to that value, printed as kotlin.Unit. Unit being a type is what lets generic code treat all functions uniformly. Nothing has no values at all: it is the return type of functions that never return normally, such as fail below, which always throws. Because Nothing is a subtype of every type, a throw or a fail call can be used wherever any value is expected.

    fun fail(m: String): Nothing =
        throw Error(m)
    
    fun main() {
        val x: Any = 5
        val u: Unit = println(x)
        // 5
        println(u)
        // kotlin.Unit
    }
  7. 7.How do ranges work in Kotlin?

    In short: a..b is a closed range including both ends, a..<b or until excludes the end, downTo counts down, step changes the increment, and in tests membership.

    Ranges describe sequences of values and are used in for loops, in membership tests and in when branches. 1..5 includes both ends, while 1..<5, or 1 until 5, stops before 5, which suits indexes. downTo builds a descending progression and step sets the stride, so 10 downTo 1 step 3 visits 10, 7, 4 and 1. The in operator checks membership, and 4 in 1..<4 is false because the end is excluded. Ranges of comparable values, such as chars or strings, also support in, and for integer ranges the compiler generates a plain loop without creating any object.

    for (i in 10 downTo 1 step 3) {
        print("$i ")
    }
    println()
    // 10 7 4 1
    println(4 in 1..<4)
    // false

How the diagnostic asks it

One question from the Kotlin bank, exactly as a sitting would show it. The bank has 4 on variables & types and 30 across Kotlin.

Variables & Types · easyKT-001

What does this Kotlin code print?

val xs = mutableListOf(1, 2)
xs.add(3)
println(xs)
  1. 1It does not compile: xs is a val
  2. 2[1, 2]
  3. 3[1, 2, 3]correct
  4. 4It throws an UnsupportedOperationException

val means the variable cannot be reassigned: xs will always refer to the same list object. It says nothing about that object, and a MutableList can be changed through any reference to it, so add(3) works and the list prints as [1, 2, 3]. The compile-error option confuses a read-only variable with an immutable value; xs = mutableListOf() would be the error. [1, 2] assumes the add was ignored. UnsupportedOperationException is what a truly unmodifiable Java list throws, but mutableListOf returns an ordinary ArrayList. To prevent changes to the contents, expose the list as a read-only List type.

Measure it

Reading answers tells you what’s true. A diagnostic tells you what you get wrong.

10 Kotlin questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.

What the readiness test measures · how the score is computed

By Harshit · updated