One of Kotlin’s most significant features is its null safety system. In Java, null pointer exceptions are a common source of bugs. Kotlin addresses this issue by differentiating between nullable and non - nullable types.
// Non - nullable variable
var name: String = "John"
// This will cause a compilation error
// name = null
// Nullable variable
var nullableName: String? = "Jane"
nullableName = null
// Safe call operator
val length = nullableName?.length
println(length)
// Elvis operator
val safeLength = nullableName?.length ?: 0
println(safeLength)
In the code above, the String
type is non - nullable by default. To make a variable nullable, we append a ?
to the type. The safe call operator ?.
allows us to call a method on a nullable object without risking a null pointer exception. The Elvis operator ?:
provides a default value if the left - hand side expression is null.
Data classes are a convenient way to create classes that are mainly used to hold data. Kotlin automatically generates useful methods such as equals()
, hashCode()
, toString()
, and copy()
for data classes.
data class Person(val name: String, val age: Int)
fun main() {
val person1 = Person("Alice", 25)
val person2 = Person("Alice", 25)
println(person1 == person2) // true, because of auto - generated equals()
println(person1.toString()) // Person(name=Alice, age=25)
val person3 = person1.copy(age = 26)
println(person3) // Person(name=Alice, age=26)
}
In this example, the Person
data class has two properties: name
and age
. The copy()
method allows us to create a new instance of the data class with some properties changed.
Kotlin supports first - class functions, which means functions can be treated as variables. Lambdas are anonymous functions that can be passed as arguments to other functions. Higher - order functions are functions that take other functions as parameters or return functions.
// Lambda expression
val sum: (Int, Int) -> Int = { a, b -> a + b }
println(sum(3, 5))
// Higher - order function
fun operateOnNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
val result = operateOnNumbers(4, 6, sum)
println(result)
Here, the sum
variable is a lambda expression that takes two integers and returns their sum. The operateOnNumbers
function is a higher - order function that takes two integers and a function as parameters and applies the function to the integers.
Extension functions allow us to add new functions to existing classes without inheriting from them or modifying their source code.
fun String.removeWhitespaces(): String {
return this.replace(" ", "")
}
fun main() {
val text = "Hello World"
val newText = text.removeWhitespaces()
println(newText) // HelloWorld
}
In this example, we define an extension function removeWhitespaces()
for the String
class. Inside the extension function, this
refers to the instance of the class on which the function is called.
Kotlin has become the preferred language for Android development due to its concise syntax and null safety features. It reduces the amount of boilerplate code and makes the code more readable and maintainable.
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
textView.text = "Button clicked!"
}
}
}
This is a simple Android activity written in Kotlin. The kotlinx.android.synthetic
package allows us to access views in the layout file directly without using findViewById()
.
Kotlin can be used for server - side development with frameworks like Ktor and Spring Boot. Ktor is a lightweight and asynchronous framework for building web applications.
import io.ktor.application.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/") {
call.respondText("Hello, World!")
}
}
}.start(wait = true)
}
This code creates a simple HTTP server using Ktor. When a client makes a GET request to the root path (/
), the server responds with the text “Hello, World!”.
Kotlin can be used for scripting purposes. You can run Kotlin scripts directly from the command line without the need to compile them first.
// script.kts
fun factorial(n: Int): Int {
return if (n <= 1) 1 else n * factorial(n - 1)
}
val number = 5
println("Factorial of $number is ${factorial(number)}")
To run this script, you can use the Kotlin command - line tool: kotlinc - script script.kts
.
userList
instead of ul
.lazy
delegate for this purpose.val expensiveObject: ExpensiveObject by lazy {
ExpensiveObject()
}
The expensiveObject
will be initialized only when it is first accessed.
Kotlin is a powerful and versatile programming language that offers many features to make software development more efficient and less error - prone. Its core concepts such as null safety, data classes, lambdas, and extension functions provide a solid foundation for building various types of applications. In typical usage scenarios like Android development, server - side development, and scripting, Kotlin shines with its concise syntax and interoperability. By following best practices in code readability, memory management, and testing, intermediate to advanced software engineers can make the most of Kotlin in their projects.