Kotlin Data Types

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.

Understanding Kotlin Type System

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.

Number Types in Kotlin

Integer Types

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()  

Floating-Point Types

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  

Character and String Types

Char Type

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 Type

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 Type

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  

Array Types

Arrays are reference types in Kotlin data types that store multiple elements of the same type.

Generic Arrays

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)  

Primitive Arrays

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)  

Collection Types

Lists

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

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

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()  

Nullable Types

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  

Type Conversion and Casting

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  
    }  
}  

Comprehensive Example: Student Management System

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.