Kotlin introduces some distinct types that may be unfamiliar to developers with a Java background. In this blog, we will delve into three such types: Any, Unit, and Nothing.
Any
//SOURCE CODE
package kotlin
/**
* The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
*/
public open class Any {
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
}
- The base of the class structure. Each Kotlin class is derived from
Any
. - Comparable to
Object
in Java. - There are three methods available for overriding:
equals()
,hashCode()
, andtoString()
. That's why, when we override methods in any class, these three choices are frequently suggested by the IDE. - Non-nullable by default. When we want a variable to hold null, we use
Any?
.
Example
fun printAny(value: Any?) {
println(value.toString())
}
fun main() {
printAny("Hello, World!") // Prints: Hello, World!
printAny(123) // Prints: 123
}
//When decompiled, Any becomes Object in Java
public static final void printAny(@Nullable Object value) {
String var1 = String.valueOf(value);
System.out.println(var1);
}
Unit
//SOURCE CODE
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"
}
- Equivalent to
void
in Java but unlikevoid
,Unit
is a genuine class with a single instance (singleton). - Illustrate a function that generates no significant output.
- In Kotlin, when a return type is not specified for a function, the default return type is
Unit
.
Example
fun printMessage(message: String): Unit { //There is no need to explicitly write Unit
println(message)
}
fun main() {
printMessage("Hello, Unit!") // Prints: Hello, Unit!
}
//When decompiled, Unit becomes void in Java
public static final void printMessage(@NotNull String message) {
Intrinsics.checkNotNullParameter(message, "message");
System.out.println(message);
}
Example: Functional Type
fun runBlock(block: ()->Unit) {
block()
}
fun main() {
runBlock { println("Here") } // Prints: Here
}
Here, () -> Unit
represents a function type. The Unit
signifies that this function type does not produce any significant output.
When specifying a function type, it is mandatory to include Unit
.
Nothing
//SOURCE CODE
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()
- Indicates that a function will not return a value under normal circumstances.
- Subtype of all well-formed Kotlin types, including user-defined ones.
- Utilized for operations that do not conclude, whether due to raising an exception or entering a never-ending loop.
- It is impossible to instantiate
Nothing
, and no class can extend or derive from it. - Functions that have a return type of
Nothing
don't return any value, not even the default return typeUnit
. - Using the
Nothing
return type in Kotlin helps prevent bugs by indicating that certain functions do not return. When a function withNothing
as its return type is called, the compiler recognizes that it won't continue past this point and provides anUnreachable code
warning.
Example
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
fun main() {
// This will throw an exception and never return normally
fail("This is an error!")
println("Hello") // Compiler gives warning "Unreachable code"
}
//When decompiled, Nothing becomes Void in Java
//Void is part of the java.lang package, acts as a reference to objects that wrap the Java primitive type void. It is uninstantiable.
@NotNull
public static final Void fail(@NotNull String message) {
Intrinsics.checkNotNullParameter(message, "message");
throw (Throwable)(new IllegalArgumentException(message));
}