Unit, Any and Nothing in Kotlin

Kotlin has some new things: Unit Any and Nothing, here is my understanding of these three brothers.

Unit

First, look at the definition of Unit in Kotlin:

package kotlin

/**
 * The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java.
 */
public object Unit {
    override fun toString() = "kotlin.Unit"
}

As you can see, first of all, Unit itself is a singleton represented by object, so it can be understood that Kotlin has a class that has only one singleton object called >Unit . This type is similar to Void in Java. Since in Kotlin, all methods/functions are expressions, expressions always have a value, so each method must have a return value. If there is no explicit specification with return, then generally speaking, it will automatically add Unit for us, which is equivalent to this:


fun returnUnit():Unit{
    return unit
}
    

The return value type is Unit, and the singleton object Unit of Unit is actually returned.

Any

First look at how Kotlin is defined:

package kotlin

/**
 * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
 */
public open class Any {
    /**
     * Indicates whether some other object is "equal to" this one. Implementations must fulfill the following
     *requirements:
     *
     * * Reflexive: for any non-null value `x`, `x.equals(x)` should return true.
     * * Symmetric: for any non-null values `x` and `y`, `x.equals(y)` should return true if and only if `y.equals(x)` returns true.
     * * Transitive: for any non-null values `x`, `y`, and `z`, if `x.equals(y)` returns true and `y.equals(z)` returns true, then `x. equals(z)` should return true.
     * * Consistent: for any non-null values `x` and `y`, multiple invocations of `x.equals(y)` consistently return true or consistently return false, provided no information used in `equals` comparisons on the objects is modified.
     * * Never equal to null: for any non-null value `x`, `x.equals(null)` should return false.
     *
     * Read more about [equality](https://kotlinlang.org/docs/reference/equality.html) in Kotlin.
     */
    public open operator fun equals(other: Any?): Boolean

    /**
     * Returns a hash code value for the object. The general contract of `hashCode` is:
     *
     * * Whenever it is invoked on the same object more than once, the `hashCode` method must consistently return the same integer, provided no information used in `equals` comparisons on the object is modified.
     * * If two objects are equal according to the `equals()` method, then calling the `hashCode` method on each of the two objects must produce the same integer result.
     */
    public open fun hashCode(): Int

    /**
     * Returns a string representation of the object.
     */
    public open fun toString(): String
}

According to the comments, Any is actually the same as Object in Java, that is to say, Any in Kotlin replaces Object in Java and becomes the parent class of all classes in Kotlin. But this statement is not very rigorous, because Any is not empty, and there is a Any? in Kotlin
, which refers to the nullable Any . Obviously, Any? is the parent class of Any, then strictly speaking, Any? is the parent class of all classes, Any is just the parent class of all non-nullable classes (that is, without ?).

Nothing

Nothing is the most difficult concept to understand, different from Unit as for Void, Any for Object , Nothing does not have a similar concept in Java. Nothing is defined as follows:

package kotlin

/**
 * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example,
 * if a function has the return type of Nothing, it means that it never returns (always throws an exception).
 */
public class Nothing private constructor()

Nothing is a class, and the class constructor is private, which means we cannot construct a Nothing object from the outside. As mentioned above, every method has a return value, and the return value is at least one Unit, which is for normal methods. If the return type of a method is defined as Nothing , then this method cannot return normally. It can be understood that all methods in Koltin are expressions, that is, they all have return values, so normal methods return Unit , and methods that cannot return normally return Nothing . For example, define the following two methods:


fun test1(): Nothing{
    while (true) {}
}

fun test2(): Nothing{
    while (false) {}
}



The test1() method can be compiled and passed, but the program will always be caught in a loop and cannot return normally when it is executed; test2() can return normally when it is executed at first glance , but because the return type is defined as Nothing, this sentence is contradictory. It has been agreed that it cannot be returned normally (the return type is defined as Nothing), and the internal logic of your method is fine. , returned to me, then there is a problem, so he actually failed to compile, and it is easy to understand: I need to return an object of class Nothing, but because Nothing The class is not open, and the constructor is private, so there is no way to return an object of it. How to let him compile it? An exception can be thrown:

fun test2(): Nothing{
    while (false) {}
    throw Exception()
}

Well, now I still can’t return normally because I threw an exception, so I declare the return type as Nothing and there is no problem. Similar usage, for example, there is a method TODO in Kotlin:


fun test3() {
    TODO()
}

@kotlin.internal.InlineOnly
public inline fun TODO(): Nothing = throw NotImplementedError()

Because it is necessary to throw an exception, it is destined to fail to return normally, so it returns the Nothing type. The return value type of the test3() method should be the default Unit, or other self-defined return types, but in fact, because TODO() is called code> , so a Nothing is returned (not returned normally), so the compilation can pass, why? Some articles understand Nothing as a subclass of all other classes, that is to say, Nothing is a subclass of other classes, so you can use One returns Nothing instead, so understanding is no problem. But there is a question, isn’t Kotlin & amp; Java single inheritance? If Nothing is a subclass of all classes, wouldn’t that be multiple inheritance? In fact, there is a concept here, which I also recently learned in “Kotlin Core Programming”. In fact, “inheritance” and “subclassing” are two concepts. We say that class A inherits class B, that is, A extends B, which emphasizes some implementations in B, which can be reused in A; and class A is a class The subclass of B emphasizes that class A can be used where class B is needed. The angles of the two are different. Single inheritance means that from the perspective of inheritance, the top-level parent class of all classes is Any (Object in Java), so everyone can reuse the parent class existing implementations of . And subclassing can be replaced in all places that need to use the parent class. For example, if a method needs to return an Any, then I actually return an Int object , is also no problem. So, Nothing can replace the return type of the original method, from the perspective of subclassing, because it can be replaced, so Nothing is a subclass of all classes, which is the same as a single Inheritance is non-conflicting. Referring to this statement, there is also an emptyList in Kotlin:

/**
 * Returns an empty read-only list. The returned list is serializable (JVM).
 * @sample samples.collections.Collections.Lists.emptyReadOnlyList
 */
public fun <T> emptyList(): List<T> = EmptyList

internal object EmptyList : List<Nothing>...

Because Nothing is a subclass of other types, according to the generic covariance, emptyList can replace the place where List is needed .

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Java skill treeHome pageOverview 108557 people are studying systematically