Nothing & Any Quiz
KOTLIN › Types & Classes
What is Nothing in Kotlin's type system?
- An alias for null
- The bottom type: a subtype of every other type, with no instances
- A synonym for Unit when a function has no return statement
- Java's void mapped into Kotlin
Answer: The bottom type: a subtype of every other type, with no instances
Nothing is the bottom type. It sits below every type in the hierarchy and can never be instantiated. Functions typed Nothing never return normally.
Why does this compile without a type error?
- throw returns Unit, which is compatible with String
- The compiler ignores the right side of ?: for type checking
- throw is an expression of type Nothing, a subtype of String
- Elvis always returns the left side, so the right side's type doesn't matter
Answer: throw is an expression of type Nothing, a subtype of String
throw is an expression typed Nothing. Since Nothing is a subtype of every type, it unifies with String and the overall expression types as String.
What is the type of x here?
- Any
- Any?
- Nothing
- Nothing?
Answer: Nothing?
Without an explicit type, the compiler infers the type of a bare null literal as Nothing? -- the type whose only value is null.
What is the return type of TODO()?
- Unit
- Any
- Nothing
- Void
Answer: Nothing
TODO() always throws NotImplementedError, so it never returns. Its return type is Nothing, which lets it stand in for any return type.
Which statement about Any is correct?
- Any is the supertype of all types, including nullable types
- Any is the supertype of all non-nullable types; Any? covers nullable ones too
- Any and Object are identical at the source level
- Any inherits from java.lang.Object in Kotlin source
Answer: Any is the supertype of all non-nullable types; Any? covers nullable ones too
Any is the root of non-nullable types. Any? is the true top of the hierarchy, encompassing both nullable and non-nullable types. At the JVM level Any maps to Object, but in Kotlin source they are distinct.
Why can emptyList() be assigned to List<String>?
- The compiler special-cases emptyList() to ignore type parameters
- emptyList() returns List<Any> which is a supertype of List<String>
- emptyList() is backed by a List<Nothing> singleton, and Nothing is a subtype of String
- List is invariant, so this only works because the list is empty
Answer: emptyList() is backed by a List<Nothing> singleton, and Nothing is a subtype of String
emptyList() is fun <T> emptyList(): List<T> -- the compiler infers T from context. Its implementation returns a singleton typed List<Nothing>. Because List is covariant (out T) and Nothing <: String, that singleton is assignable to List<String>.
What is the difference between Unit and Nothing?
- They are interchangeable; both mean "no value"
- Unit has one instance and means "returns but no useful value"; Nothing has zero instances and means "never returns"
- Nothing is nullable Unit
- Unit is for suspend functions; Nothing is for regular functions
Answer: Unit has one instance and means "returns but no useful value"; Nothing has zero instances and means "never returns"
Unit has exactly one value (the Unit object) and signals a function returns but its return value is meaningless. Nothing has no instances and signals a function never completes normally.
What does this function return for flag = false?
- It returns null
- It returns Unit
- It throws NotImplementedError
- It doesn't compile
Answer: It throws NotImplementedError
TODO() has type Nothing, so the compiler never reaches it when flag is false. When flag is true the throw fires. When false, the function falls through with no explicit return, which in Kotlin is an implicit return Unit.
Which of these is NOT a function that returns Nothing?
- TODO()
- error("boom")
- throw IllegalStateException()
- println("done")
Answer: println("done")
TODO(), error(), and a bare throw all have type Nothing because they never return. println() returns Unit -- it completes normally.
What does Any declare (its own members)?
- equals(), hashCode(), toString(), clone(), finalize()
- equals(), hashCode(), toString()
- No members; they are inherited from java.lang.Object
- equals(), hashCode(), toString(), getClass()
Answer: equals(), hashCode(), toString()
Kotlin's Any declares exactly three members: equals(), hashCode(), and toString(). Java's Object has more (like clone(), wait(), notify()), but those are not part of Any's Kotlin API.
What happens at run time?
- Prints 42 because Nothing? coerces to Int
- Prints null because null is a valid Any?
- Compile error: null cannot be stored in a List<Any?>
- Throws NullPointerException at the add call
Answer: Prints null because null is a valid Any?
null has type Nothing?, which is a subtype of Any?. Adding it to a MutableList<Any?> is perfectly legal, and printing it shows null.
Why does the compiler require an else branch here?
- when always requires else in Kotlin
- Any is open, so the compiler cannot know all subtypes at compile time
- Nothing can appear at run time as an unexpected type
- is String and is Int do not cover nullable types
Answer: Any is open, so the compiler cannot know all subtypes at compile time
Any is open -- any class can extend it, so the compiler cannot enumerate all possible subtypes. Only sealed types provide exhaustive when without else.
What is the inferred type of result?
- String
- Any
- Nothing
- String?
Answer: String
The when is exhaustive (all branches of the sealed class are covered). The Success branch returns String. The Error branch calls error(), which returns Nothing. The union of String and Nothing is String, because Nothing is a subtype of String.
Can you write a function with return type Nothing that does NOT throw?
- Yes, by returning null
- Yes, by returning Unit
- Yes, with an infinite loop
- No, a Nothing function must always throw
Answer: Yes, with an infinite loop
A function that loops forever never returns, so its return type is Nothing. It does not throw -- it simply never completes. Nothing means "no normal return", not "must throw".