The Ugly Thruth About Kotlin’s Null Safety LIE

543 words

Maciej Najbar
4 min readApr 17, 2023

WHY IT MATTERS: Predictable software contains less bugs.

  • NPEs are thrown when we don’t expect them.
  • The Billion Dollar Mistake is a LIE.

When I hear „null safety” I remember this:

Don’t trust your eyes. Sometimes salt looks like sugar.

GO DEEPER: Kotlin and Java live in symbiosis.

  • They both run on Java Virtual Machine.
  • They both compile to the same Bytecode.
  • You can use Java class in Kotlin code and vice versa.

They must play by the same rules. How is it possible that one language offers null safety and the other doesn’t?
They DON’T and Kotlin is even more dangerous.

Kotlin offers safe calls that get rid of boilerplate code.

Kotlin

return parent?.child?.grandchild?.age ?: 0

Java

if (parent != null) {
if (parent.child != null) {
if (parent.child.grandchild != null) {
return parent.child.grandchild.age;
}
}
}
return 0;

Less boilerplate helps us quickly spot problems. Everything at compile time. This comes very handy. Is that reason to call Kotlin null safe though?

FIRST EXAMPLE: Beware of Plaftorm Types.

  • Platform Type is a pure Java type with no modifiers (annotations like @Nullable or @NotNull).
  • It can be either strict or optional. You decide.

Such type cannot be trusted. If this can be null but not necessarily, it should be considered nullable by default.

SECOND EXAMPLE: Java and Kotlin generic types look alike.
Using Java generics in Kotlin passes responsibility on a programmer.

  • Optional types require safe calls (fortunately).
  • Strict types become Platform Types.

THIRD EXAMPLE: You never know what external services return.

  • Applications connect to some third parties (e.g. Backend).
  • Even when the contract is agreed upon it may change.

Designing a service that others integrate with is extremely hard to maintain. A small change that is backward incompatible can break experience for clients.

I have a policy: Zero trust to 3rd parties. Hence everything from the backend is considered nullable.

Let’s see an example.

Since Kotlin allows me to use Java features I can use REFLECTION.

Using reflection is considered as a mistake in professional development.
This is also a lie…

I’m not saying to use reflection in your production code. I say it’s extremely helpful in libraries.

  • jUnit — it uses reflection.
  • Mockito? — reflection.
  • I bet you don’t parse JSON yourself but you use a library instead. GSON? — again, reflection!

This is very important that whatever comes from outside your application consider it nullable.
If you don’t, you can end up in the state that the compiler says the value cannot be null, but we already know it can.

Such null can live silently in your app until you perform an operation on a null-referenced object.

THE BOTTOM LINE: NPEs are thrown when they are not expected.

You would never write such thing.

I guess it’s why it’s not highlighted. You EXPECT that after such command, your app will fail.
It doesn’t mean that nulls are bad thing though.

Those of you who have ever fought your significant other know, that by saying SOMETHING you can make a great mistake, but saying NOTHING may be even worse.
Nulls exist. It’s on us to learn how to use them instead trying to workaround because it’s inconvenient.

Design your code to be PREDICTABLE the rest will fix itself.

Did you like the story? Leave a comment and don’t forget to clap.

--

--