Kotlin data types define what kind of values variables can store and how much memory they occupy. Whether you’re building Android applications or server-side programs, mastering Kotlin data types will make your programming journey smoother and more efficient.
Kotlin data types are statically typed, meaning the compiler knows the exact type of every variable at compile time. This comprehensive guide will walk you through all Kotlin data types, from basic primitive types to complex collection types, helping you understand when and how to use each one effectively.
Kotlin data types are divided into several categories that make the language both powerful and safe. Unlike Java, Kotlin treats everything as objects, which means all Kotlin data types have methods and properties you can call on them. The Kotlin type system includes basic types, collection types, and special types that handle null safety.
The most commonly used Kotlin data types include numbers, characters, booleans, strings, and arrays. Each of these Kotlin data types serves specific purposes and has unique characteristics that make them suitable for different programming scenarios.
Kotlin provides several integer data types to handle whole numbers of different sizes:
Byte Type:
The Byte type in Kotlin data types represents 8-bit signed integers ranging from -128 to 127.
val smallNumber: Byte = 42
val negativeSmallNumber: Byte = -100
Short Type:
Short is one of the Kotlin data types that stores 16-bit signed integers from -32,768 to 32,767.
val mediumNumber: Short = 1000
val negativeShort: Short = -15000
Int Type:
Int represents 32-bit signed integers and is the default type for integer literals in Kotlin data types.
val regularNumber: Int = 1000000
val calculations: Int = 50 * 20
Long Type:
Long handles 64-bit signed integers, perfect for large numbers in Kotlin data types.
val bigNumber: Long = 9876543210L
val timestamp: Long = System.currentTimeMillis()
Kotlin data types include two floating-point types for decimal numbers:
Float Type:
Float stores 32-bit floating-point numbers with single precision.
val price: Float = 19.99f
val percentage: Float = 85.5f
Double Type:
Double is the default floating-point type in Kotlin data types, storing 64-bit double-precision numbers.
val preciseValue: Double = 3.141592653589793
val scientificNotation: Double = 1.23e-4
The Char type in Kotlin data types represents a single 16-bit Unicode character.
val letter: Char = 'A'
val digit: Char = '5'
val unicodeChar: Char = '\u03A9' // Omega symbol
Characters in Kotlin data types cannot be treated as numbers directly, unlike some other programming languages. You need explicit conversion functions.
val charCode: Int = letter.code
val charFromCode: Char = 65.toChar()
String is one of the most frequently used Kotlin data types for handling text data. Strings in Kotlin are immutable, meaning you cannot change individual characters after creation.
val greeting: String = "Hello, Kotlin!"
val multilineString: String = """
This is a multiline string
that preserves formatting
and line breaks
""".trimIndent()
String templates make working with this Kotlin data type extremely convenient:
val name: String = "Developer"
val age: Int = 25
val introduction: String = "My name is $name and I am $age years old"
val calculation: String = "The result is ${10 + 5}"
Boolean is one of the essential Kotlin data types that can only hold two values: true or false.
val isKotlinFun: Boolean = true
val isComplicated: Boolean = false
val comparisonResult: Boolean = 10 > 5
Boolean operations are fundamental when working with this Kotlin data type:
val andResult: Boolean = true && false // false
val orResult: Boolean = true || false // true
val notResult: Boolean = !true // false
Arrays are reference types in Kotlin data types that store multiple elements of the same type.
val numbers: Array<Int> = arrayOf(1, 2, 3, 4, 5)
val names: Array<String> = arrayOf("Alice", "Bob", "Charlie")
val mixedArray: Array<Any> = arrayOf(1, "Hello", true, 3.14)
Kotlin data types include specialized array types for primitives to avoid boxing overhead:
val intArray: IntArray = intArrayOf(10, 20, 30, 40)
val doubleArray: DoubleArray = doubleArrayOf(1.1, 2.2, 3.3)
val booleanArray: BooleanArray = booleanArrayOf(true, false, true)
Lists are immutable by default in Kotlin data types, providing ordered collections of elements.
val readOnlyList: List<String> = listOf("apple", "banana", "cherry")
val mutableList: MutableList<Int> = mutableListOf(1, 2, 3)
Sets in Kotlin data types store unique elements without duplicates.
val readOnlySet: Set<String> = setOf("red", "green", "blue")
val mutableSet: MutableSet<Int> = mutableSetOf(10, 20, 30)
Maps store key-value pairs and are essential Kotlin data types for associative data.
val readOnlyMap: Map<String, Int> = mapOf("Alice" to 25, "Bob" to 30)
val mutableMap: MutableMap<String, String> = mutableMapOf()
One of the most powerful features of Kotlin data types is null safety. Any type can be made nullable by adding a question mark.
val nullableString: String? = null
val nullableInt: Int? = 42
val nonNullString: String = "This cannot be null"
Working with nullable Kotlin data types requires safe call operators:
val length: Int? = nullableString?.length
val safeLength: Int = nullableString?.length ?: 0
Kotlin data types don’t support implicit conversions between numeric types. You must use explicit conversion functions:
val intValue: Int = 100
val longValue: Long = intValue.toLong()
val doubleValue: Double = intValue.toDouble()
val stringValue: String = intValue.toString()
Smart casting is another feature of Kotlin data types that automatically casts types when the compiler can guarantee type safety:
fun processValue(value: Any) {
if (value is String) {
println(value.length) // value is automatically cast to String
}
}
Here’s a complete example demonstrating various Kotlin data types in a practical scenario:
// Import statements
import java.time.LocalDate
import java.time.Period
// Data class using multiple Kotlin data types
data class Student(
val id: Long,
val name: String,
val age: Byte,
val gpa: Double,
val isActive: Boolean,
val courses: List<String>,
val grades: Map<String, Char>,
val birthDate: String? = null
)
// Main function demonstrating Kotlin data types
fun main() {
// Creating student records using various Kotlin data types
val student1 = Student(
id = 1001L,
name = "Emma Johnson",
age = 20.toByte(),
gpa = 3.85,
isActive = true,
courses = listOf("Mathematics", "Physics", "Computer Science"),
grades = mapOf(
"Mathematics" to 'A',
"Physics" to 'B',
"Computer Science" to 'A'
),
birthDate = "2004-03-15"
)
val student2 = Student(
id = 1002L,
name = "Michael Chen",
age = 19.toByte(),
gpa = 3.92,
isActive = true,
courses = listOf("Biology", "Chemistry", "Statistics"),
grades = mapOf(
"Biology" to 'A',
"Chemistry" to 'A',
"Statistics" to 'B'
)
)
// Working with collections of Kotlin data types
val students: MutableList<Student> = mutableListOf(student1, student2)
// Array of student IDs using primitive Kotlin data types
val studentIds: LongArray = longArrayOf(1001L, 1002L, 1003L, 1004L)
// Map for course enrollment count
val courseEnrollment: MutableMap<String, Int> = mutableMapOf()
// Processing students and demonstrating type operations
println("=== Student Management System ===")
println()
for (student in students) {
println("Student Information:")
println("ID: ${student.id}")
println("Name: ${student.name}")
println("Age: ${student.age}")
println("GPA: ${"%.2f".format(student.gpa)}")
println("Status: ${if (student.isActive) "Active" else "Inactive"}")
println("Courses: ${student.courses.joinToString(", ")}")
// Working with nullable types
student.birthDate?.let { birthDate ->
println("Birth Date: $birthDate")
// You could add age calculation here
} ?: println("Birth Date: Not provided")
// Grade analysis using character data type
val gradePoints: Double = student.grades.values.map { grade ->
when (grade) {
'A' -> 4.0
'B' -> 3.0
'C' -> 2.0
'D' -> 1.0
else -> 0.0
}
}.average()
println("Calculated GPA from grades: ${"%.2f".format(gradePoints)}")
// Count course enrollments
student.courses.forEach { course ->
courseEnrollment[course] = courseEnrollment.getOrDefault(course, 0) + 1
}
println("=" .repeat(40))
}
// Statistics using various Kotlin data types
val totalStudents: Int = students.size
val activeStudents: Int = students.count { it.isActive }
val averageAge: Double = students.map { it.age.toDouble() }.average()
val averageGPA: Double = students.map { it.gpa }.average()
val highPerformers: List<Student> = students.filter { it.gpa >= 3.8 }
println("System Statistics:")
println("Total Students: $totalStudents")
println("Active Students: $activeStudents")
println("Average Age: ${"%.1f".format(averageAge)} years")
println("Average GPA: ${"%.2f".format(averageGPA)}")
println("High Performers (GPA >= 3.8): ${highPerformers.size}")
println()
println("Course Enrollment Summary:")
courseEnrollment.forEach { (course, count) ->
println("$course: $count ${if (count == 1) "student" else "students"}")
}
// Demonstrating type checking and casting
println()
println("Type Information:")
val sampleValue: Any = student1.gpa
when (sampleValue) {
is Double -> println("GPA is a Double with value: $sampleValue")
is String -> println("Value is a String: $sampleValue")
is Boolean -> println("Value is a Boolean: $sampleValue")
else -> println("Unknown type")
}
// Working with arrays and primitive types
println()
println("Student ID Array Operations:")
println("All IDs: ${studentIds.joinToString(", ")}")
println("First ID: ${studentIds.first()}")
println("Last ID: ${studentIds.last()}")
println("Array size: ${studentIds.size}")
// Character operations
val gradeLetters: CharArray = charArrayOf('A', 'B', 'C', 'D', 'F')
println()
println("Available Grades: ${gradeLetters.joinToString(", ")}")
// String operations and templates
val systemInfo: String = """
Student Management System Report
Generated on: ${java.time.LocalDateTime.now()}
Total Records: $totalStudents
System Status: ${if (totalStudents > 0) "Operational" else "No Data"}
""".trimIndent()
println()
println(systemInfo)
}
Expected Output:
=== Student Management System ===
Student Information:
ID: 1001
Name: Emma Johnson
Age: 20
GPA: 3.85
Status: Active
Courses: Mathematics, Physics, Computer Science
Birth Date: 2004-03-15
Calculated GPA from grades: 3.67
========================================
Student Information:
ID: 1002
Name: Michael Chen
Age: 19
GPA: 3.92
Status: Active
Courses: Biology, Chemistry, Statistics
Birth Date: Not provided
Calculated GPA from grades: 3.67
========================================
System Statistics:
Total Students: 2
Active Students: 2
Average Age: 19.5 years
Average GPA: 3.89
High Performers (GPA >= 3.8): 2
Course Enrollment Summary:
Mathematics: 1 student
Physics: 1 student
Computer Science: 1 student
Biology: 1 student
Chemistry: 1 student
Statistics: 1 student
Type Information:
GPA is a Double with value: 3.85
Student ID Array Operations:
All IDs: 1001, 1002, 1003, 1004
First ID: 1001
Last ID: 1004
Array size: 4
Available Grades: A, B, C, D, F
Student Management System Report
Generated on: 2025-06-06T10:30:45.123
Total Records: 2
System Status: Operational
This comprehensive example demonstrates how different Kotlin data types work together in real-world applications. You can see how primitive types like Byte, Long, and Double store numeric data, how String handles text, how Boolean manages true/false values, and how collections like List and Map organize complex data structures.
Understanding Kotlin data types is fundamental for effective programming. Each type serves specific purposes and offers unique advantages. Whether you’re working with simple variables or complex data structures, choosing the right Kotlin data types will make your code more efficient, readable, and maintainable. Practice using these types in your own projects to master their behavior and capabilities.