Skip to main content

Kotlin Data Types

Introduction

When you're building applications in Kotlin, understanding data types is fundamental. Data types define what kind of information a variable can hold, how much memory it will occupy, and what operations can be performed on it. In Kotlin, all data types are objects, which means they have methods and properties, unlike some programming languages where primitive types are separate from objects.

This guide will walk you through Kotlin's type system, showing you how to use different data types effectively and efficiently in your programs.

Basic Data Types in Kotlin

Kotlin provides several built-in data types that handle the most common programming needs. Let's explore each of them:

Numbers

Kotlin has various numeric types to represent integers and floating-point numbers:

Integer Types

kotlin
val byte: Byte = 127         // 8 bits, range: -128 to 127
val short: Short = 32767 // 16 bits, range: -32768 to 32767
val int: Int = 2147483647 // 32 bits, range: -2,147,483,648 to 2,147,483,647
val long: Long = 9223372036854775807L // 64 bits, note the 'L' suffix

Floating-Point Types

kotlin
val float: Float = 3.14f     // 32 bits, note the 'f' suffix
val double: Double = 3.14159265358979 // 64 bits, more precision than Float

Let's see a simple example showing these numeric types in action:

kotlin
fun main() {
val intValue: Int = 100
val longValue: Long = 1234567890L
val byteValue: Byte = 25

val floatValue: Float = 3.14f
val doubleValue: Double = 3.14159265358979

println("Int: $intValue")
println("Long: $longValue")
println("Byte: $byteValue")
println("Float: $floatValue")
println("Double: $doubleValue")

// Mathematical operations
val sum = intValue + byteValue // 125
val product = floatValue * doubleValue

println("Sum (Int + Byte): $sum")
println("Product (Float * Double): $product")
}

Output:

Int: 100
Long: 1234567890
Byte: 25
Float: 3.14
Double: 3.14159265358979
Sum (Int + Byte): 125
Product (Float * Double): 9.8686

Characters

In Kotlin, characters are represented by the Char type. They are written with single quotes:

kotlin
val letterA: Char = 'A'
val digit5: Char = '5'
val newLine: Char = '\n' // Escape sequence for new line
val unicodeSymbol: Char = '\u00A9' // Unicode for copyright symbol ©

Booleans

The Boolean type represents logical values. It can have only two values: true or false:

kotlin
val isActive: Boolean = true
val isCompleted: Boolean = false

// Boolean operations
val andResult = isActive && isCompleted // Logical AND
val orResult = isActive || isCompleted // Logical OR
val notResult = !isActive // Logical NOT

println("AND result: $andResult") // false
println("OR result: $orResult") // true
println("NOT result: $notResult") // false

Strings

Strings in Kotlin are sequences of characters. They are represented by the String type and can be written with double quotes:

kotlin
val greeting: String = "Hello, Kotlin!"
val name: String = "Alex"
val message = "Welcome, $name" // String interpolation

// Multi-line strings
val paragraph = """
This is a multi-line string.
No need for escape characters.
You can write multiple lines easily.
""".trimIndent()

println(greeting)
println(message)
println(paragraph)

Output:

Hello, Kotlin!
Welcome, Alex
This is a multi-line string.
No need for escape characters.
You can write multiple lines easily.

Type Inference

Kotlin has strong type inference capabilities, which means the compiler can often determine the type automatically:

kotlin
// Type explicitly specified
val explicitDouble: Double = 3.14

// Type inferred by the compiler
val inferredDouble = 3.14 // This is also a Double

println("Explicit double: $explicitDouble")
println("Inferred double: $inferredDouble")

Both variables are of type Double, but in the second case, we didn't have to specify it explicitly.

Type Conversion

Kotlin requires explicit conversion between number types to prevent precision loss:

kotlin
fun main() {
val intNumber = 100

// This won't compile:
// val longNumber: Long = intNumber

// Explicit conversion is required:
val longNumber: Long = intNumber.toLong()

// Other conversion methods:
val doubleFromInt = intNumber.toDouble()
val floatFromLong = longNumber.toFloat()
val stringFromInt = intNumber.toString()

println("Integer: $intNumber")
println("Long from Int: $longNumber")
println("Double from Int: $doubleFromInt")
println("String from Int: $stringFromInt")

// Converting string to number
val numberString = "42"
val parsedInt = numberString.toInt()

println("Parsed integer: $parsedInt")
}

Output:

Integer: 100
Long from Int: 100
Double from Int: 100.0
String from Int: 100
Parsed integer: 42

Arrays

Arrays in Kotlin are represented by the Array class, with specialized classes for primitive types:

kotlin
fun main() {
// Creating arrays
val numbers = arrayOf(1, 2, 3, 4, 5)
val strings = arrayOf("apple", "banana", "cherry")

// Specialized arrays for primitive types (more efficient)
val intArray = intArrayOf(10, 20, 30)
val doubleArray = doubleArrayOf(1.1, 2.2, 3.3)

// Creating an array with a specific size and initializer function
val squaredNumbers = Array(5) { i -> i * i } // [0, 1, 4, 9, 16]

// Accessing elements
println("First number: ${numbers[0]}")
println("Second fruit: ${strings[1]}")

// Modifying elements
numbers[0] = 10
println("Updated first number: ${numbers[0]}")

// Iterating through an array
print("Squared numbers: ")
for (number in squaredNumbers) {
print("$number ")
}
println()

// Array size
println("Number of fruits: ${strings.size}")
}

Output:

First number: 1
Second fruit: banana
Updated first number: 10
Squared numbers: 0 1 4 9 16
Number of fruits: 3

Nullable Types

One of Kotlin's most powerful features is its handling of null values. By default, types cannot hold null:

kotlin
// This won't compile:
// val name: String = null

// To allow null values, add a question mark to the type
val name: String? = null

// Working with nullable types
fun main() {
val nonNullName: String = "Alex"
val nullableName: String? = null

// Safe call operator (?.)
println("Length of nonNullName: ${nonNullName.length}")
println("Length of nullableName: ${nullableName?.length}") // Prints null

// Elvis operator (?:)
val length = nullableName?.length ?: 0
println("Length (with default): $length") // Prints 0

// Not-null assertion operator (!!)
// Use with caution! Will throw NullPointerException if the value is null
try {
val forcedLength = nullableName!!.length // This throws an exception
} catch (e: NullPointerException) {
println("Caught NullPointerException: ${e.message}")
}
}

Output:

Length of nonNullName: 4
Length of nullableName: null
Length (with default): 0
Caught NullPointerException: null

Real-World Examples

Let's explore some practical applications of Kotlin data types:

Building a User Profile System

kotlin
fun main() {
val user = createUser("Alice", 28, "[email protected]")
displayUserProfile(user)

// Optional fields with nullable types
val partialUser = createUser("Bob", 32, null)
displayUserProfile(partialUser)
}

// Creating a data class to hold user information
data class User(
val name: String,
val age: Int,
val email: String?
)

fun createUser(name: String, age: Int, email: String?): User {
// Validate data
require(name.isNotBlank()) { "Name cannot be empty" }
require(age > 0) { "Age must be positive" }

// Email validation (simplified)
if (email != null && !email.contains('@')) {
throw IllegalArgumentException("Invalid email format")
}

return User(name, age, email)
}

fun displayUserProfile(user: User) {
println("===== User Profile =====")
println("Name: ${user.name}")
println("Age: ${user.age}")
println("Email: ${user.email ?: "Not provided"}")
println("========================")
}

Output:

===== User Profile =====
Name: Alice
Age: 28
Email: [email protected]
========================
===== User Profile =====
Name: Bob
Age: 32
Email: Not provided
========================

Temperature Conversion Application

kotlin
fun main() {
println("Temperature Conversion Tool")
println("==========================")

val celsiusTemps = doubleArrayOf(0.0, 25.0, 100.0, -40.0)

println("Temperature conversions:")
for (celsius in celsiusTemps) {
val fahrenheit = celsiusToFahrenheit(celsius)
val kelvin = celsiusToKelvin(celsius)

println("$celsius°C = $fahrenheit°F = $kelvin K")
}

// Convert user input
println("\nEnter a temperature in Celsius:")
val userInput = readLine()

try {
val userCelsius = userInput?.toDoubleOrNull()
if (userCelsius != null) {
val userFahrenheit = celsiusToFahrenheit(userCelsius)
println("$userCelsius°C is $userFahrenheit°F")
} else {
println("Invalid input: Please enter a valid number")
}
} catch (e: Exception) {
println("Error processing input: ${e.message}")
}
}

fun celsiusToFahrenheit(celsius: Double): Double {
return celsius * 9/5 + 32
}

fun celsiusToKelvin(celsius: Double): Double {
return celsius + 273.15
}

When run, this program will output temperature conversions and then prompt for user input.

Summary

In this guide, we've covered Kotlin's rich data type system:

  • Basic types: Numbers (Int, Long, Double, Float, Byte, Short), Char, Boolean, and String
  • Type inference: Letting Kotlin determine the type automatically
  • Type conversion: Converting between different numeric types
  • Arrays: Creating and manipulating collections of data
  • Nullable types: Safely handling potentially null values

Understanding Kotlin's data types is essential for writing safe, efficient code. The type system helps prevent common errors while giving you the flexibility to express complex ideas.

Practice Exercises

  1. Type Explorer: Create a program that declares variables of each basic Kotlin type and prints their values and types.
  2. Array Manipulation: Create an array of integers, then write functions to calculate its sum, average, minimum, and maximum values.
  3. Null Safety Challenge: Write a function that takes a nullable string parameter and returns its length if it's not null, or -1 if it is null. Try implementing it using different null-handling techniques in Kotlin.
  4. Temperature Tracker: Build a program that tracks daily temperatures for a week, calculates statistics, and identifies the hottest and coldest days.

Additional Resources

Remember that mastering data types is one of the most important steps toward becoming proficient in any programming language. Take time to experiment with different types and understand how they work together in your Kotlin programs.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)