Kotlin to Java Differences
I posted about the things I like about Kotlin (see here), but are there any stumbling blocks for a developer that is moving from Java? This post lists some of the things that might seem odd at first when considering the transition.
What I’m going to focus on is the aspects that might get overlooked by someone new to Kotlin if they did not know about the differences. I make no judgement on whether it is good or bad.
Null Safety
I covered how Kotlin can protect your code from hitting NullPointerException
at run time. It does this by disallowing nulls to be assigned unless you make a conscious decision to allow a variable to hold a null. But there will be ocassions when you simply cannot be sure that a variable passed as a parameter to your code will not be null.
This could be from legacy Java code in your project that has not been modified, or when interoperating with other Java libraries. Another source may be your own inexperience with Kotlin that causes you to use the ?
after most variable declarations.
To avoid the proliferation of null checking within Kotlin, a series of operators is available to keep the language concise. The first is the safe call operator, ?.
, which can be used to access a property or method of the object, evaluating to null if the object itself is null. These can be chained to access the underlying properties.
fun doSomethingWithFavColour(person : Person?) {
println(person?.attributes?.favouriteColour)
}
If either the person
object itself or the attributes
property is null, then null will be passed to the println
function without any exception being raised. This is a lot neater than an if statement that has to check both person and attributes, but might not be obvious at first glance.
Defaulting: Elvis Operator
Extending the above a little further, what if we want to return a default value in the event that something we expect not to be null turns out to be so? Or maybe we want to throw an exception; not a NullPointerException
, but something we define that is more meaningful. Kotlin provides the Elvis operator, ?:
, to allow this.
The simplest case is to provide a default value. Given a parameter that might be null, the operator can check this, return the value if not null or the default value. The following will print either the string, s
, or and empty string provided in the default location.
fun dontPrintNull(s: String?) {
println(s ?: "")
}
You can also throw an exception or execute any code from the elvis operator to take effect when the subject is null. The following makes little sense, but demonstrates this ability.
fun nullsNotAllowed(s: String?) {
s?: throw RuntimeException("Not allowed nulls")
println(s)
}
Safe Casting
In an earlier post, I mentioned the smart casting feature of Kotlin, which allows you to avoid explicitly stating the cast if you have used the is
check to verify the object is that type. Casting is done with the as
keyword, replacing the brackets in Java. But it will throw a ClassCastException
just as in Java if the type is incorrect.
There is another clever tool for casting within Kotling called safe casting and it is done with the as?
operator. Usually it is combined with the elvis operator above, say for example to override the functionality of the equals
function.
data class MyObj( ... properties) {
override fun equals(o :Any?): Boolean {
val other = o as? MyObj ?: return false
// ... continue with comparison
}
}
The o as? MyObj
expression will return null
if the object is not of the specified type, and that will be picked up by the elvis operator to immediately return false. Otherwise it can continue to do the comparison of other
to its own properties.