Sobes.tech
Middle+

What are the features of using the Nothing type in generics?

sobes.tech AI

Answer from AI

The Nothing type in Kotlin is a special type that has no instances. Its main purpose in generics is to indicate the absence of a return value or a situation where the execution flow does not terminate normally (for example, when throwing an exception).

Features of using Nothing in generics:

  • Covariance: Nothing is a subtype of any other type (Any? ultimately). Thanks to this, if a generic is declared with a covariant parameter (out), then List<Nothing> can be assigned to a variable of type List<String> (or List<Any>). This is useful, for example, for representing an empty collection with an unspecified element type.

    // Covariant List
    fun processStrings(list: List<String>) {
        println(list)
    }
    
    val emptyList: List<Nothing> = listOf()
    processStrings(emptyList) // This works because List<Nothing> is a subtype of List<String>
    
  • Contravariance: If a generic is declared with a contravariant parameter (in), using Nothing as an upper bound (in Nothing) does not have practical sense, since Nothing is the lowest type in the hierarchy.

  • Invariance: For invariant generics (MutableList<T>), MutableList<Nothing> is not a subtype of MutableList<String>.

    var stringList: MutableList<String> = mutableListOf("hello")
    // val nothingList: MutableList<Nothing> = mutableListOf() // Will not compile
    
    // stringList = nothingList // Will not compile
    
  • Using as a return type: Functions that always throw an exception can explicitly specify Nothing as their return type. This clearly signals to the compiler and other developers that the function will never return a value.

    fun fail(message: String): Nothing {
        throw IllegalStateException(message)
    }
    
    //val x: String = fail("Error") // The compiler knows this line is never reachable after calling fail
    
  • Constraints: Nothing can be used in generic constraints, but using it as a lower bound (<T : Nothing>) means that the type T can only be Nothing (or essentially never instantiated). Using Nothing as an upper bound (<T : Any?>) does not add new constraints, as any type is by default a subtype of Any?.

In general, Nothing in generics serves to explicitly indicate situations of "no instance" or "no return value," especially in the context of covariance, allowing working with collections that "will never contain elements."

What are the features of using the Nothing type in… - sobes.tech