[Kotlin Pearls] Unit, Nothing, Any (And Null)

DZone 's Guide to

[Kotlin Pearls] Unit, Nothing, Any (And Null)

The Type Hierarchy in Kotlin is unparalleled in terms of interoperability.

· Java Zone ·
Free Resource

Kotlin pearls

String of [Kotlin] pearls

How to Take Advantage of Kotlin Special Types

It should be apparent, even to the casual reader of this blog, that I really like Kotlin as a language. One of the reasons is its Type Hierarchy, which is both very easy to work with and extremely powerful. It is also quite close to the Java Type System, so the interoperability is excellent.

You may also like: 5 Things You Will Like in Kotlin as a Java Developer

To take full advantage of the Kotlin Type Hierarchy, it is essential to understand how these three special types work. We will look in detail at Unit, Nothing, and Any, and compare against their Java corresponding classes.

Finally, we also consider null and how types ending with ? fit into these categories.


The Unit type in Kotlin is the equivalent to the void type in Java.

Or, if you prefer, is the result value of any statement (for example println()).

fun whatIsLove(){
  println("Baby don't hurt me!")

In Kotlin, we have two way to define a function or a method: as a statement, with the above syntax similar to Java or as an expression.

We can rewrite any statement without return type as an expression returning Unit:

fun whatIsLove(): Unit = println("Baby don't hurt me!")

Expressions are usually easier to read than statements, at least if we can keep them short. Long methods are not a good idea anyway.

In the Kotlin standard library, Unit is simply defined as an object, implicitly inheriting from Any, with a single method override for toString().

public object Unit { 
  override fun toString() = "kotlin.Unit"

 Objects in Kotlin are classes with only one instance, which is created in the class static initializer.

For example:

object JustAnObject {
    override fun toString(): String {
        return "JustAnObject"

It is translated in ByteCode as a class JustAnObject with a static method INSTANCE to retrieve the singleton instance.

GETSTATIC com/ubertob/unitnothingany/JustAnObject.INSTANCE : Lcom/ubertob/unitnothingany/JustAnObject;
public final static Lcom/ubertob/unitnothingany/JustAnObject; INSTANCE

When operating with Java code, the Kotlin compiler is smart enough to translate any return void into Unit and the same for special function types.

For example, we can pass a Java lambda of type Consumer<Integer> to a function expecting a parameter of type (Int) -> Unit .

public static Consumer<Integer> printNum = x -> System.out.println("Num " + x);
fun callMe(block: (Int) -> Unit): Unit = (1..100).forEach(block)
fun main(){
    callMe { Lambdas.printNum } //it works fine

Note also that in Java, there is a class called Void, which, confusedly, it is only indirectly related to the keyword void and cannot be instantiated, so null is the only valid return value for a function with the result of type Void.

In case you are wondering, Void is needed to represent in Java reflection and Generics the concept of methods returning void, but differently from Unit is not the actual result values of those methods.


Brace yourself here because this is the trickiest type here.

 Nothingis a class (not an object) which is a subclass of any other class, including the final ones. There is a catch, though: it is impossible to instantiate a Nothing object because there is only a private constructor.

Its declaration is pretty simple:

public class Nothing private constructor() 

Now, you may wonder what is the point of having such a class if we cannot instantiate it. Actually, it is pretty useful, as we are going to show.

Since it's not possible to pass a value of type Nothing, it represents the result of "a function that never returns." For example, because it throws an exception or because it has an infinite loop.

In mathematics and functional programming, Nothing is called the Bottom Type and represented with the symbol.

In a computer program, any function, regardless of its return type, may not return a value, because of errors or infinite computations. Kotlin makes this property explicit with the Nothing type.

Let's see some useful use cases now.

The first is the TODO() function that you can use everywhere when you don't want to specify an implementation yet.

public inline fun TODO(): Nothing = throw NotImplementedError() 

Did you ever wonder how it can replace any possible expected return type? It works only because Nothing is a subtype of any class.

fun determineWinner(): Player = TODO() 
//It compiles because Nothing is a subclass of Player

Note that in Java, you cannot write a similar function.

static Void todo(){
  throw new RuntimeException("Not Implemented");
String myMethod(){   
    return todo(); //it doesnt' compile because Void is not a String

The second example is represented by all empty collections:

fun findAllPlayers(): List<Player> = emptyList()

How can the EmptyList of Kotlin standard library be a valid List<Player>? Look at the implementation solves the mystery:

public fun <T> emptyList(): List<T> = EmptyList 
//generic function using type inference
object EmptyList : List<Nothing> ... //ultimate covariancefun readUser(id: UserId): User? = …

As you probably guessed, it works because of Nothing type. Similarly, there are also emptyMap(), emptySet(), etc.

The third example is maybe less typical of the previous two, but it is still quite useful.

Let's say you have a function that can fail, for example, reading a user from database.

A simple and sensible choice can be returning a null when the user cannot be found. The signature can be like this:

fun readUser(id: UserId): User? = ... 

Sometimes, we need more information about what exactly went wrong (connection can be down, table not exist ecc.) and let the called decide how to handle the failure.

Here, Nothing came to the rescue! A brilliant solution is to provide a callback in case of an error that returns Nothing.

inline fun readUser(id: UserId, onError: (DbError) -> Nothing): User = ... 

How does it work? Let's see a full example:

fun createUserPage(id: UserId): HtmlPage {
    val user = readUser(id) { err ->
        when (err) {
            is InvalidStatement -> 
return@createUserPage throw Exception(err.parseError)
            is UserNotFound -> 
return@createUserPage HtmlPage("No such user!")
    return HtmlPage("User ${user.name}") //happy case

As you can see, both throwing an Exception and a non-local return is a valid Nothing type.

To be able to call a non-local return from a lambda, you need to inline the calling function, readUser in this case.

A possible further evolution of this error handling pattern is wrapping the outcome on a functional Either with onError method. This will give us even more flexibility and composition possibilities at the cost of slightly higher code complexity. It is a matter for a future blog post anyway. Let me know if you would be interested.

It is simple to have a private constructor but how can Nothing be a subclass of anything else? How does it work "under the hood"?

It's all compiler magic, in the ByteCode Nothing is translated as Void, while Unit is translated as void.

fun neverReturn(): Nothing {
    throw Exception("never!")
public final static neverReturn()Ljava/lang/Void;

Finally, it can be useful to remember the differences between Nothing and Unit:

fun fooOne(): Unit { while (true) {} }
fun fooZero(): Nothing { while (true) {} }
//both ok
fun barOne(): Unit { println("hi")}
fun barZero(): Nothing { println("hi") }  //error
//barZero not compiling

Note that Nothing is a subtype of Unit, that's why the first compile but not the last one.


Any in Kotlin is on the top of the hierarchy. All other types descend from Any.

From the class documentation:

" The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass."

It works like Java Object, but it has a much leaner signature:

public open class Any {
    public open operator fun equals(other: Any?): Boolean
    public open fun hashCode(): Int
    public open fun toString(): String

As a comparison java.lang.Object has 11 methods, of which five are about synchronization ( wait, notify, notifyAll).

This is clearly an example of the advantages of coming later; it might seem a good idea at the time, but now having synchronization primitives on any possible object now seems unnecessary. There is also a reference on Valhalla project mailing list about it.

Looking at the code for Any, we can also see that is one of the few classes in the Kotlin stdlib that is open, meaning that is possible to inherit directly from it. This is necessary because every Kotlin class automatically inherits from Any, even if you don't have to write it explicitly, you may do.

class MyClass: Any() {
    fun bye(): String = "bye bye"

Under the hood, at the JVM level, the Any type doesn't exist and it gets compiled to java.lang.Object

For example:

fun whatIcanDoWithAny(obj: Any){

Generate this bytecode where even if you are not familiar with the format. You can easily spot the actual type of the parameter (in bold).

public final static whatIcanDoWithAny(Ljava/lang/Object;)V
    // annotable parameter count: 1 (visible)
    // annotable parameter count: 1 (invisible)
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
    ALOAD 0
    LDC "obj"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    ALOAD 0
    INVOKEVIRTUAL java/lang/Object.toString ()Ljava/lang/String;

Even if they are not easily accessible from Kotlin, all Kotlin objects do have all the methods missing in Any, like notify, wait, etc.

This also makes possible to pass any Kotlin object to a Java method which is expecting an Object.

Finally, note that the Any class implements the equals operator, which is mapped on the Java equals method of Object class. As a consequence, equals== is the only operator in Kotlin that needs to be overridden and you cannot change its signature, for example, to return some kind of Difference class instead of a Boolean.


The last protagonist of this post is not a type but it unique because it has no type. If you want, you can consider null the opposite of Nothing: a value without a Type, while Nothing is a Type that cannot be instantiated.

In Kotlin, null can form special union types with any other type, making them "nullable" and denoting them with the question mark. So String? is the union of the type String plus the null. In this way, Kotlin with the help of smart casts and special operators make easy to handle null safely.

What about our special types?

Unit? allows you to return a statement or null. I don't know of any interesting use of it.

Nothing? Is particular because it is the only way to force a function to have null as the only possible result. Still no practical use as far as I know.

Any? is important because it is the equivalent of Java Object since in Java you can return null.
Also when declaring a generic class MyClass<T> the implicit bound of T is Any?, like in Java. If you want to restrict your generic class to non-nullable types, you have to state it explicitly: MyClass<T: Any>

Another way to look at null is syntax sugar for the Optional/Maybe type, that can represent a value or the lack of.

Just an exercise let's rewrite map and flatmap as extension functions for any nullable in Kotlin.

fun <A:Any, B:Any> A?.map(f: (A) -> B): B? = when(this) {
    null -> null
    else -> f(this)
fun <A:Any, B:Any> A?.flatMap(f: (A) -> B?): B? = when(this) {
    null -> null
    else -> f(this)

The full code for these examples and more is on my GitHub project.

I hope you liked this post, if so please applaud it and follow me on Twitter and Medium.

The feedback so far on this series of posts has been very positive; thanks to everybody who recommended and shared my posts!

Previous Posts

[Kotlin Pearls] Extensions: The Good, the Bad, and the Ugly  

[Kotlin Pearls] Multiple Inheritance  

[Kotlin Pearls] Lambdas With a Context — ProAndroidDev 

Start a discussion" > 

java ,kotlin ,null ,any ,unit ,nothing

Published at DZone with permission of Uberto Barbini , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}