Learning Kotlin syntax is essential for modern Android development and server-side programming. Kotlin syntax offers a perfect blend of conciseness and readability, making it an ideal choice for developers transitioning from Java or starting fresh. This comprehensive guide will walk you through every aspect of Kotlin syntax, from basic declarations to advanced features that make Kotlin syntax so powerful and developer-friendly.
Kotlin syntax provides two main ways to declare variables: var
for mutable variables and val
for immutable ones. Understanding this fundamental aspect of Kotlin syntax is crucial for writing effective code.
var userName = "Alice" // Type inferred as String
var userAge: Int = 25 // Explicit type declaration
userName = "Bob" // Can be reassigned
val pi = 3.14159 // Type inferred as Double
val maxUsers: Int = 100 // Explicit type declaration
// pi = 3.14 // Compilation error - cannot reassign
Kotlin syntax supports various primitive data types including Int
, Long
, Float
, Double
, Boolean
, Char
, and String
. The type inference feature in Kotlin syntax eliminates the need for explicit type declarations in most cases.
Function declaration is one of the most important aspects of Kotlin syntax. Kotlin functions are declared using the fun
keyword, and Kotlin syntax offers multiple ways to define them.
fun greetUser(name: String): String {
return "Hello, $name!"
}
// Single-expression function
fun addNumbers(a: Int, b: Int) = a + b
fun createUser(name: String, age: Int = 18, isActive: Boolean = true): String {
return "User: $name, Age: $age, Active: $isActive"
}
Kotlin syntax allows functions to have default parameter values, making function calls more flexible and reducing the need for method overloading.
Kotlin syntax provides intuitive control flow statements that are both powerful and easy to read.
val score = 85
val grade = if (score >= 90) {
"A"
} else if (score >= 80) {
"B"
} else {
"C"
}
The when
expression in Kotlin syntax is more powerful than Java’s switch statement:
fun getSeasonMessage(month: Int): String {
return when (month) {
12, 1, 2 -> "Winter season"
in 3..5 -> "Spring season"
in 6..8 -> "Summer season"
in 9..11 -> "Fall season"
else -> "Invalid month"
}
}
// For loop with range
for (i in 1..5) {
println("Number: $i")
}
// For loop with collection
val fruits = listOf("apple", "banana", "orange")
for (fruit in fruits) {
println("Fruit: $fruit")
}
// While loop
var counter = 0
while (counter < 3) {
println("Counter: $counter")
counter++
}
Kotlin syntax provides powerful collection types with built-in functions that make data manipulation straightforward.
// Immutable list
val readOnlyList = listOf("kotlin", "java", "python")
// Mutable list
val mutableList = mutableListOf<String>()
mutableList.add("swift")
mutableList.add("dart")
// Immutable map
val countryMap = mapOf("US" to "United States", "UK" to "United Kingdom")
// Mutable map
val cityMap = mutableMapOf<String, Int>()
cityMap["New York"] = 8000000
cityMap["London"] = 9000000
val uniqueNumbers = setOf(1, 2, 3, 2, 1) // Contains only 1, 2, 3
val mutableSet = mutableSetOf<String>()
mutableSet.add("unique")
Kotlin syntax makes object-oriented programming more concise compared to Java while maintaining full functionality.
class Student(val name: String, var age: Int) {
var grade: String = "A"
fun study(subject: String) {
println("$name is studying $subject")
}
fun getInfo(): String {
return "Student: $name, Age: $age, Grade: $grade"
}
}
Kotlin syntax includes data classes that automatically generate equals()
, hashCode()
, toString()
, and copy()
methods:
data class Product(val name: String, val price: Double, val category: String)
One of the most important features of Kotlin syntax is null safety, which helps prevent the dreaded NullPointerException.
var nullableString: String? = null
var nonNullString: String = "Hello"
// Safe call operator
val length = nullableString?.length
// Elvis operator
val displayText = nullableString ?: "Default text"
// Not-null assertion
val forceLength = nullableString!!.length // Use with caution
Kotlin syntax allows you to extend existing classes with new functionality through extension functions:
fun String.isPalindrome(): Boolean {
val cleaned = this.lowercase().replace(" ", "")
return cleaned == cleaned.reversed()
}
// Usage
val text = "A man a plan a canal Panama"
println(text.isPalindrome()) // true
Kotlin syntax supports functional programming concepts with higher-order functions and lambda expressions.
val numbers = listOf(1, 2, 3, 4, 5)
// Filter even numbers
val evenNumbers = numbers.filter { it % 2 == 0 }
// Map to squares
val squares = numbers.map { it * it }
// Custom higher-order function
fun processNumbers(numbers: List<Int>, operation: (Int) -> Int): List<Int> {
return numbers.map(operation)
}
Kotlin syntax includes powerful string interpolation features that make string formatting much cleaner:
val name = "Alice"
val age = 30
val city = "New York"
// Simple string template
val greeting = "Hello, $name!"
// Expression in template
val message = "Next year, $name will be ${age + 1} years old"
// Multi-line string with trimIndent
val address = """
Name: $name
Age: $age
City: $city
""".trimIndent()
Here’s a comprehensive example that demonstrates various Kotlin syntax features in a practical application:
data class Student(
val id: Int,
val name: String,
var grade: Double,
val subjects: MutableList<String> = mutableListOf()
) {
fun addSubject(subject: String) {
if (!subjects.contains(subject)) {
subjects.add(subject)
}
}
fun getGradeLevel(): String = when {
grade >= 90 -> "Excellent"
grade >= 80 -> "Good"
grade >= 70 -> "Average"
else -> "Needs Improvement"
}
}
class StudentManager {
private val students = mutableListOf<Student>()
fun addStudent(student: Student) {
students.add(student)
println("Added student: ${student.name}")
}
fun findStudentById(id: Int): Student? {
return students.find { it.id == id }
}
fun getStudentsByGradeRange(minGrade: Double, maxGrade: Double): List<Student> {
return students.filter { it.grade in minGrade..maxGrade }
}
fun getAverageGrade(): Double {
return if (students.isNotEmpty()) {
students.map { it.grade }.average()
} else 0.0
}
fun printAllStudents() {
students.forEach { student ->
println("ID: ${student.id}, Name: ${student.name}, Grade: ${student.grade}")
println("Grade Level: ${student.getGradeLevel()}")
println("Subjects: ${student.subjects.joinToString(", ")}")
println("---")
}
}
}
// Extension function for Student
fun Student.isHonorStudent(): Boolean = grade >= 85
fun main() {
val manager = StudentManager()
// Create students
val student1 = Student(1, "Alice Johnson", 92.5)
student1.addSubject("Mathematics")
student1.addSubject("Physics")
student1.addSubject("Chemistry")
val student2 = Student(2, "Bob Smith", 78.0)
student2.addSubject("History")
student2.addSubject("English")
val student3 = Student(3, "Carol Davis", 88.5)
student3.addSubject("Biology")
student3.addSubject("Mathematics")
// Add students to manager
manager.addStudent(student1)
manager.addStudent(student2)
manager.addStudent(student3)
// Find student by ID
val foundStudent = manager.findStudentById(2)
foundStudent?.let { student ->
println("Found student: ${student.name} with grade ${student.grade}")
}
// Get students in grade range
val goodStudents = manager.getStudentsByGradeRange(80.0, 100.0)
println("\nStudents with grades between 80-100:")
goodStudents.forEach { println("${it.name}: ${it.grade}") }
// Check honor students using extension function
println("\nHonor Students:")
manager.getStudentsByGradeRange(0.0, 100.0)
.filter { it.isHonorStudent() }
.forEach { println("${it.name} is an honor student with grade ${it.grade}") }
// Calculate and display average grade
val averageGrade = manager.getAverageGrade()
println("\nClass average grade: ${"%.2f".format(averageGrade)}")
// Print all students
println("\nAll Students:")
manager.printAllStudents()
// Demonstrate null safety
val nullableStudent: Student? = manager.findStudentById(999)
val studentName = nullableStudent?.name ?: "Student not found"
println("\nSearching for student ID 999: $studentName")
// Lambda expressions with collections
val topStudents = manager.getStudentsByGradeRange(0.0, 100.0)
.filter { it.grade >= 85 }
.sortedByDescending { it.grade }
.take(2)
println("\nTop 2 Students:")
topStudents.forEach { student ->
val gradeInfo = "Grade: ${student.grade} (${student.getGradeLevel()})"
println("${student.name} - $gradeInfo")
}
}
Expected Output:
Added student: Alice Johnson
Added student: Bob Smith
Added student: Carol Davis
Found student: Bob Smith with grade 78.0
Students with grades between 80-100:
Alice Johnson: 92.5
Carol Davis: 88.5
Honor Students:
Alice Johnson is an honor student with grade 92.5
Carol Davis is an honor student with grade 88.5
Class average grade: 86.33
All Students:
ID: 1, Name: Alice Johnson, Grade: 92.5
Grade Level: Excellent
Subjects: Mathematics, Physics, Chemistry
---
ID: 2, Name: Bob Smith, Grade: 78.0
Grade Level: Average
Subjects: History, English
---
ID: 3, Name: Carol Davis, Grade: 88.5
Grade Level: Good
Subjects: Biology, Mathematics
---
Searching for student ID 999: Student not found
Top 2 Students:
Alice Johnson - Grade: 92.5 (Excellent)
Carol Davis - Grade: 88.5 (Good)
This comprehensive example showcases the elegance and power of Kotlin syntax, demonstrating how various language features work together to create clean, readable, and maintainable code. The Kotlin syntax makes it easy to express complex logic while maintaining type safety and null safety throughout your applications.