71. The difference between “==” and “===” operators in Kotlin
In Kotlin, == and === are different:
Checks if two values are equal (like .equals() in Java).
val a = "Bind"
val b = "Bind"
println(a == b) // ✅ true → because values are equal
Kotlin internally calls:
a?.equals(b) ?: (b == null)
Checks if two references point to the same object in memory.
val a = "Bind"
val b = "Bind"
println(a === b) // May be true due to string interning
val x = String("Bind".toCharArray())
val y = String("Bind".toCharArray())
println(x == y) // ✅ true → values equal
println(x === y) // ❌ false → different objects in memory
Operator | Meaning | Checks if... |
---|---|---|
== | Structural Equality | values are the same (.equals()) |
=== | Referential Equality | both refer to the same object |
72. The purpose of the operator modifier in Kotlin
In Kotlin, the operator modifier allows you to define or overload operators (like +, -, [], in, ==, etc.) for your custom types (classes).
It enables natural, readable syntax when working with custom objects by letting you write:
val sum = a + b // instead of a.plus(b)
Example: Overloading + Operator
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
}
val p1 = Point(1, 2)
val p2 = Point(3, 4)
val result = p1 + p2 // Calls operator fun plus()
Common Operators You Can Overload
Operator | Function to Overload |
---|---|
+ | operator fun plus() |
- | operator fun minus() |
* | operator fun times() |
/ | operator fun div() |
% | operator fun rem() |
[] | operator fun get() / set() |
in | operator fun contains() |
== | operator fun equals() |
<, > | operator fun compareTo() |
73. Explain the use of the @JvmOverloads annotation in Kotlin
The @JvmOverloads annotation is used in Kotlin to automatically generate overloaded methods for Java interoperability when calling Kotlin code from Java.
Kotlin supports default parameter values, but Java does not. So if you write this in Kotlin:
fun greet(name: String, message: String = "Hello") {
println("$message, $name!")
}
You can call:
greet("John") // OK in Kotlin
greet("John", "Hi") // OK
But from Java, you must pass all parameters, since Java doesn’t understand default values.
Solution with @JvmOverloads
@JvmOverloads
fun greet(name: String, message: String = "Hello") {
println("$message, $name!")
}
This generates the following overloads for Java:
greet("John"); // Uses default message
greet("John", "Hi"); // Uses provided message
When to Use @JvmOverloads
Scenario | Use It? |
---|---|
Kotlin code only | ❌ Not needed |
Kotlin code used from Java | ✅ Yes |
Android custom views & constructors | ✅ Common use case |
74. The difference between lateinit and lazy initialization in Kotlin
Feature | lateinit | lazy |
---|---|---|
Type of Property | var (mutable) | val (read-only) |
Initialization Timing | Initialized later, manually | Initialized on first access, automatically |
Nullable Allowed? | ❌ Cannot be used with nullable types | ✅ Can be used with nullable types |
Primitive Types Allowed? | ❌ Not allowed with primitive types | ✅ Allowed with primitives (e.g., Int, Double) |
Requires Non-null Type? | ✅ Yes (must not be nullable) | ❌ No |
Common Use Case | For variables like UI elements, injected dependencies | For expensive computations (e.g., caching, config loading) |
Throws Exception If Unused? | ✅ UninitializedPropertyAccessException if accessed before init | ❌ Safe: won't throw unless inside lazy block |
Thread Safety | ❌ Not thread-safe | ✅ Thread-safe by default (LazyThreadSafetyMode.SYNCHRONIZED) |
Syntax Example | lateinit var name: String | val name: String by lazy { "John" } |
75. The purpose of the const modifier in Kotlin
In Kotlin, the const modifier is used to declare compile-time constants.
Syntax:
const val PI = 3.14
Not Allowed Inside Functions
fun example() {
// ❌ This will cause a compile error
const val name = "Bind the Logic"
}
Allowed Locations
const val APP_NAME = "BindTheLogic" // ✅ Top-level
object Config {
const val VERSION = "1.0" // ✅ In object
}
class MyClass {
companion object {
const val TAG = "MyClassTag" // ✅ In companion object
}
}
Why Use const?
Benefit | Explanation |
---|---|
✅ Faster access | Value is inlined at compile-time |
✅ Used in annotations | Required for annotation parameters |
✅ Safer constants | Cannot be changed or re-evaluated at runtime |
✅ Reduces memory use | No backing field; value is baked into bytecode |
val vs const val
Feature | val | const val |
---|---|---|
Time | Evaluated at runtime | Evaluated at compile-time |
Scope | Can be local or global | Only top-level / object / companion |
Allowed types | Any type | Only primitives & String |
Used in annotations | ❌ No | ✅ Yes |