Kotlin for Java Developers (Part 1) covers
- Data classes
- Null safety
- Immutability by default
This part continues on the key differences that a Java developer should be aware of when switching from Java to Kotlin. Part 2 of the series covers
- Using
new
Keyword - Utilise Extension Functions
- Use
when
Instead Ofif
Orswitch
Using new
Keyword
This is a rather small section, but I've confusion about this topic several times. In Kotlin, you don't need the new
keyword to instantiate an object. The object creation is simpler, as Kotlin automatically understands that you want to create a new instance of a class.
Java way:
MyClass myClass = new MyClass();
Kotlin way:
val myClass = MyClass()
- You simply call the class constructor directly, like you would with a function call.
-
val
is used to declare an immutable variable that will hold the reference to the object (see immutability in part 1).
Utilise Extension Functions
Extension functions are a powerful feature, which allows you to add new functionality to existing classes without modifying their source-code! This is particularly useful when you need to enhance the capabilities of libraries or classes that you don't control, or when you want to avoid subclassing or writing utility classes.
Example 1: Extension functions on strings
Java way:
In Java, you might create a utility class with a static method to add functionality to a class.
public class MyStringUtils {
public static boolean isValidEmail(String email) {
return str != null && str.contains("@"); // Simplified email validation
}
}
to use this, you would have to call it as a static method:
String email = "test@example.com";
boolean isValid = MyStringUtils.isValidEmail(email);
Kotlin way:
In Kotlin, you can add a new function to the String
class to check if a string is a valid email address.
fun String.isValidEmail(): Boolean {
return this.contains("@") // Simplified email validation
}
or even shorter:
fun String.isValidEmail() = this.contains("@")
The this
keyword refers to the object the extension function is called on. You can call this function on any
String
object:
val email = "test@example.com"
val isValid = email.isValidEmail() // direct call on the string object to the extension function
This makes the code much cleaner and more readable as it avoids the boilerplate code of utility classes or inheritance.
Example 2: Extension functions on collections
E.g. if you want a filter function to only retrieve odd numbers from a list.
Java way:
import java.util.List;
import java.util.stream.Collectors;
public class MyListUtils {
public static List<Integer> getOddNumbers(List<Integer> numbers) {
return numbers.stream()
.filter(n -> n % 2 != 0)
.collect(Collectors.toList());
}
}
and you would call it like this
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> oddNumbers = MyListUtils.getOddNumbers(numbers);
Kotlin way:
fun List<Int>.getOddNumbers() = this.filter { it % 2 != 0 }
and you would call it directly on the list:
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
val oddNumbers = numbers.getOddNumbers()
Why use extension functions?
- Cleaner code: Extension functions allow you to write code as if the function is part of an existing class, making you code-base look more natural and reduce boilerplate code.
- Reusability: You can write reusable functionality outside the class itself
References
Use when
Instead Of if
Or switch
The when
expression in Kotlin can be thought of as an advanced version of the switch
statement in Java, that is much more powerful and can also replace the if-else
statement. A key difference is, that the when
expression is not limited to checking the equality as in Java, but can handle a wide range of conditions, like types, ranges and even arbitrary expressions.
Example 1: Using when
instead of if-else
Java way:
int x = 2;
String result;
if (x == 1) {
result = "One";
} else if (x == 2) {
result = "Two";
} else if (x == 3) {
result = "Three";
} else {
result = "Unknown";
}
System.out.println(result);
Kotlin way:
val x = 2
val result = when (x) {
1 -> "One"
2 -> "Two"
3 -> "Three"
else -> "Unknown"
}
println(result)
Example 2: Using when
instead of switch
Again the same java example:
int x = 2;
String result;
switch (x) {
case 1:
result = "One";
break;
case 2:
result = "Two";
break;
case 3:
result = "Three";
break;
default:
result = "Unknown";
}
System.out.println(result);
And the Kotlin equivalent:
val x = 2
val result = when (x) {
1 -> "One"
2 -> "Two"
3 -> "Three"
else -> "Unknown"
}
println(result)
In Kotlin, there is no need for break
statements, as the when
expression automatically breaks after the first match.
Example 3: Using when
with ranges
Kotlin's when
expression can be used with ranges or collections:
val x = 5
val result = when (x) {
in 1..10 -> "Between 1 and 10"
!in 11..20 -> "Outside 11 - 20"
else -> "Other"
}
Example 4: Checking Types
You can also use when
to check the type of an unknown object, similar to instanceof
in Java:
fun checkType(obj: Any): String {
return when (obj) {
is String -> "String"
is Int -> "Int"
is Double -> "Double"
else -> "Unknown"
}
}
println(checkType("Hello")) // Prints "String"
println(checkType(42)) // Prints "Int"
println(checkType(3.14)) // Prints "Double"
println(checkType(true)) // Prints "Unknown"
References:
Interested in the next article?
Here is Part 3 of the series.
Top comments (0)