Although it is not explicitly stated that Nothing is the subtype of all types, this (among others) suggests it:
fun f(x:Float) { }
fun g(x:Char) { }
fun dead(q: Nothing) {
f(q)
g(q)
}
However, this fails with “unresolved reference”:
fun dead(q: Nothing) {
q.not()
}
Is this a bug or a feature?
Notes:
- First piece of code compiles (with warnings), second does not
- It's possible to use a
Nothing
typed receiver, for instance calling toString()
- This is legal:
{b:Boolean -> b.not()}(q)
- Upcast too:
(q as Boolean).not()
- Equivalent question for Scala
Nothing
is Nothing
for a reason. You can't call any functions on it. Besides not()
is only applicable for Boolean
so it is not present on Nothing
. In fact there are no methods on Nothing
:
/**
* 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()
The documentation pretty much explains its existence.
There is one loophole though. What happens if you return Nothing?
from a function?
fun dead(): Nothing? {
return null
}
That's right. It can only return null
:
@JvmStatic
fun main(args: Array<String>) {
dead() // will be null
}
I wouldn't say that there is a valid use case to do this but it is possible.
An example for Nothing
to indicate nothingness in trees:
sealed class Tree<out T>() {
data class Node<out T>(val value: T,
val left: Tree<T> = None,
val right: Tree<T> = None): Tree<T>()
object None: Tree<Nothing>()
}
Here Nothing
denotes a leaf node with no children.
The premise itself doesn't make sense. Nothing
is a class which can not be instantiated. You'll never have a variable that holds a Nothing
instance.
This means that a function that takes Nothing
as a parameter can never be invoked, because you can't get a Nothing
instance to pass to it. Anything you write inside it is irrelevant, as is a function like this existing in the first place.
Nothing
is made to act like a subtype to all types so that certain uses of language features like throw
and return
work nicely with the type system. In essence, the compiler lets you pass a Nothing
in places where some other type is required, because it knows that you'll never actually reach that code (because again, you can't get a Nothing
instance), so it doesn't matter what you're passing in.