skip to content

Numbers & Literals

Kotlin has no language-level primitives — Byte through Double are classes — yet they compile to JVM primitives where possible. Interviewers probe literal forms and inference (1 is Int, 1L is Long) and when boxing to java.lang wrappers actually happens.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What numeric types does Kotlin provide for whole and fractional numbers, and how do you write integer literals in hex, binary, with separators, and as a Long?

level: juniorimportance: must knowfreq 70%

answer

  1. Byte/Short/Int/Long + Float/Double
  2. 0x hex, 0b binary, no octal
  3. underscores = readability only
  4. L = Long, f/F = Float
  5. literal defaults: Int / Double

basics

~10 s

Whole numbers: Byte, Short, Int, Long. Fractional: Float, Double. Write hex as 0xFF, binary as 0b1010, use underscores like 1_000 for readability, and add an L suffix (1L) to make a Long.

solid answer

~40 s

Kotlin's built-in number types are Byte (8-bit), Short (16-bit), Int (32-bit), Long (64-bit) for integers, and Float (32-bit) and Double (64-bit) for IEEE-754 floating point. Integer literals support hexadecimal (0xFF), binary (0b1010), and underscores as visual separators (1_000_000). There is no octal literal. A trailing L makes a Long (1L); without it the literal defaults to Int (or auto-fits a target type). Floating-point literals default to Double; an f or F suffix makes a Float (1.0f). You can mix forms, e.g. 0xFF_FFL is a hex Long. All of these are real classes (Int, Long, etc.), not language-level primitives, though the compiler maps them to JVM primitives where possible.

code

kotlin · 6 lines
kotlin
val mask = 0xFF          // Int 255
val flags = 0b1010       // Int 10
val population = 8_000_000_000L  // Long
val pi = 3.14            // Double
val ratio = 0.5f         // Float
println(mask + flags)    // 265

go deeper

for a junior

Names the six types and writes 0xFF, 0b1010, 1_000, 1L, 1.0f correctly.

for a middle

Explains default inference (Int vs Long, Double for decimals) and that there is no octal.

for a senior

Notes these are classes not primitives and that auto-widening of an over-large literal picks Long.

for a principal

Connects literal/type choices to readability and JVM codegen, and reasons about when to force suffixes in APIs.

## The numeric types Kotlin has six built-in numeric types, each a real class in `kotlin` package: - **Integers:** `Byte` (8-bit), `Short` (16-bit), `Int` (32-bit), `Long` (64-bit). - **Floating point:** `Float` (32-bit IEEE-754), `Double` (64-bit IEEE-754). Unlike Java there are no `int`/`long` *language* primitives you write in source — you always use the class names. (The compiler still emits JVM primitives under the hood; see boxing.) ## Integer literal forms ```kotlin val dec = 1000 // decimal val hex = 0xFF // hexadecimal -> 255 val bin = 0b1010 // binary -> 10 val grouped = 1_000_000 // underscores are ignored, just readability val big = 1_234L // Long via L suffix ``` - **Hex** uses the `0x`/`0X` prefix; digits `0-9 a-f`. - **Binary** uses the `0b`/`0B` prefix. - **There is no octal literal** in Kotlin (no leading-zero octal like C/Java). - **Underscores** (`_`) may appear between digits as visual separators and are stripped by the compiler; they cannot lead, trail, or sit next to the prefix. - **`L` suffix** (uppercase only — lowercase `l` is disallowed to avoid confusion with `1`) makes the literal a `Long`. ## Floating-point literal forms ```kotlin val d = 1.0 // Double by default val f = 1.0f // Float via f/F suffix val sci = 1.5e3 // scientific notation -> 1500.0 (Double) ``` A literal with a decimal point or exponent defaults to **`Double`**. Add `f`/`F` for `Float`. ## Default type inference An unsuffixed integer literal is inferred as `Int` if it fits in 32 bits; if it exceeds `Int.MAX_VALUE` it is inferred as `Long` automatically. You can still force `Long` with `L` for clarity even when it fits. ```kotlin val a = 100 // Int val b = 10_000_000_000 // Long (too big for Int) val c = 100L // Long, forced ``` These literal rules apply identically across hex/binary/decimal forms.

  • Why is lowercase 'l' not allowed as a Long suffix?
    Because lowercase 'l' is visually confusable with the digit '1'; Kotlin only accepts uppercase 'L'.
  • Does Kotlin support octal literals?
    No. Only decimal, hexadecimal (0x) and binary (0b) integer literals exist; there is no leading-zero octal form.

Suffixes are like unit labels on a number: 'L' says litres (Long), 'f' says feet (Float) — same digits, different declared size.

saying these in an interview costs you the question

  • Claiming Kotlin has C-style primitives (int/long) you write in code
  • Saying a leading zero like 0777 is octal in Kotlin
  • Thinking underscores change the value or only work in certain positions arbitrarily
  • Believing an unsuffixed 1.0 is a Float
  • Using lowercase l for Long

context

open as a page

Explain how Kotlin decides whether a numeric literal is Int or Long, and how that affects an expression like `val ms = 60 * 60 * 1000 * 24 * 365`.

level: middleimportance: must knowfreq 60%

basics

~20 s

An unsuffixed integer literal is Int if it fits in 32 bits, otherwise Long. If every operand in a multiplication is Int, the math is done in Int and can overflow silently. Add an L to one operand to force Long math.

open as a page

Walk through the literal suffixes (L, f/F, and the lack of others) and explain how a small literal can initialize a Byte or Short without a suffix.

level: middleimportance: should knowfreq 40%

basics

~20 s

L makes a Long, f/F makes a Float. There is no Byte/Short suffix and no Int suffix. A small constant like 100 can be assigned to a Byte or Short variable directly because the compiler sees it fits the declared type.

open as a page

Kotlin numbers like Int are classes, not language primitives. How does the compiler represent them on the JVM, and when does boxing into java.lang wrappers happen?

level: seniorimportance: should knowfreq 45%

basics

~20 s

In source you always write the class name Int. On the JVM the compiler uses the cheap primitive int where it can, but switches to the boxed java.lang.Integer when the value must be nullable (Int?) or used as a generic type argument, like in a List<Int>.

open as a page

What are the rules and edge cases for digit underscores and radix prefixes in Kotlin numeric literals? Which forms are illegal and why?

level: middleimportance: nice to knowfreq 25%

basics

~20 s

Underscores are just visual separators between digits and don't change the value. They can't be at the start, the end, or right next to the 0x/0b prefix. Hex is 0x, binary is 0b, and there is no octal.

open as a page