Variables and Data Types
## Learning Objectives
- Understand val and var declarations
- Learn Kotlin's basic data types
- Master type inference
- Work with nullable types
## Variables
### Immutable Variables (val)
Use `val` for variables that cannot be reassigned:
```kotlin
fun main() {
val name = "Kotlin"
// name = "Java" // Error: Val cannot be reassigned
println(name)
}
```
### Mutable Variables (var)
Use `var` for variables that can be changed:
```kotlin
fun main() {
var count = 0
count = 1
count = 2
println(count) // Output: 2
}
```
### When to Use Which
- Prefer `val` by default for immutability
- Use `var` only when reassignment is necessary
- Immutable data makes code safer and easier to reason about
## Basic Data Types
### Numbers
```kotlin
fun main() {
val byte: Byte = 127 // 8-bit
val short: Short = 32767 // 16-bit
val int: Int = 2147483647 // 32-bit
val long: Long = 9223372036854775807 // 64-bit
val float: Float = 3.14f // 32-bit floating point
val double: Double = 3.14159 // 64-bit floating point
println(byte)
println(int)
println(float)
}
```
### Characters and Strings
```kotlin
fun main() {
val char: Char = 'A'
val string: String = "Hello"
val multiline = """
This is a
multiline string
""".trimIndent()
println(char)
println(string)
println(multiline)
}
```
### Booleans
```kotlin
fun main() {
val isKotlinFun: Boolean = true
val isJavaBetter: Boolean = false
println(isKotlinFun)
println(!isJavaBetter) // Logical NOT
}
```
### Arrays
```kotlin
fun main() {
val numbers = arrayOf(1, 2, 3, 4, 5)
val zeros = IntArray(5) // [0, 0, 0, 0, 0]
println(numbers[0])
println(numbers.size)
}
```
## Type Inference
Kotlin can infer types automatically:
```kotlin
fun main() {
val inferredInt = 42 // Inferred as Int
val inferredDouble = 3.14 // Inferred as Double
val inferredString = "Hi" // Inferred as String
println(inferredInt)
println(inferredDouble)
println(inferredString)
}
```
## Explicit Type Declarations
When inference is not possible, declare types explicitly:
```kotlin
fun main() {
val explicitInt: Int = 42
val explicitDouble: Double = 3.14
// Type required when initializing later
val laterInit: String
laterInit = "Initialized later"
println(explicitInt)
println(laterInit)
}
```
## Type Conversion
Kotlin does not support implicit widening:
```kotlin
fun main() {
val intVal: Int = 42
// val longVal: Long = intVal // Error: No implicit conversion
// Explicit conversion
val longVal: Long = intVal.toLong()
val doubleVal: Double = intVal.toDouble()
println(longVal)
println(doubleVal)
}
```
### Conversion Functions
- `toByte()`, `toShort()`, `toInt()`, `toLong()`
- `toFloat()`, `toDouble()`
- `toChar()`, `toString()`
## Nullable Types
Kotlin's type system distinguishes between nullable and non-nullable:
```kotlin
fun main() {
var neverNull: String = "This can't be null"
// neverNull = null // Error: Null can not be a value of type String
var nullable: String? = "This can be null"
nullable = null // OK
println(nullable)
}
```
### Nullable with Safe Default
```kotlin
fun main() {
var nullable: String? = null
// Using safe default with ?: (Elvis operator)
val length = nullable?.length ?: 0
println(length) // Output: 0
}
```
## Type Checking
```kotlin
fun main() {
val obj: Any = "Hello"
// is operator checks type
if (obj is String) {
// Smart cast - no explicit cast needed
println("Length: ${obj.length}")
}
// !is for negation
if (obj !is Int) {
println("Not an Int")
}
}
```
### Explicit Casting
```kotlin
fun main() {
val str: String = "Hello"
val obj: Any = str
// as operator for explicit casting
val casted: String = obj as String
println(casted.length)
}
```
Safe cast returns null instead of throwing:
```kotlin
fun main() {
val obj: Any = "Hello"
// as? returns null if cast fails
val casted: Int? = obj as? Int
println(casted) // Output: null
}
```
## String Templates
```kotlin
fun main() {
val name = "Kotlin"
val version = 1.9
println("Language: $name")
println("Version: $version")
println("Length: ${name.length}")
// Expression in template
println("Uppercase: ${name.uppercase()}")
}
```
## Summary
- `val` declares immutable variables, `var` declares mutable ones
- Kotlin has Int, Long, Double, Float, Boolean, Char, String types
- Type inference automatically determines types when possible
- Nullable types use `?` suffix (e.g., `String?`)
- Smart casts automatically cast types after `is` checks
- `as?` provides safe casting that returns null on failure
- String templates use `$variable` or `${expression}`
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →