kotlin的Any类

145 阅读3分钟

在 Kotlin 中,Any 是所有非空类型的超类型。换句话说,Any 是 Kotlin 类型系统的根类型。它类似于 Java 中的 Object 类,但有一些重要的区别。

  1. Nullable和非Nullable: Any 是非空类型,这意味着它不能持有 null 值。如果你想表示可以为 null 的任意类型,可以使用 Any?,即 Any 的可空版本。
  2. Smart Cast: 当你在代码中使用 is 操作符检查类型并进入分支时,Kotlin 能够智能地将实例转换为相应的类型。这使得在分支内部可以直接使用特定类型的成员。
fun example(anyValue: Any) {
    if (anyValue is String) {
        // 在这个分支中,anyValue 被智能转换为 String 类型
        println(anyValue.length)
    }
}
  1. Any 的成员函数: Any 类型提供了一些通用的成员函数,如 equals()hashCode()toString()。这些函数被所有非空类型继承,因此你可以在任何非空类型的实例上使用它们。源码如下:
/**
 * 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 fulfil 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
}
  1. Any 的使用场景: Any 类型在编写泛型代码时非常有用,因为你可以使用它表示任何非空类型的对象。同时,Any 也可以用作函数的返回类型,以通用的方式返回不同类型的结果。

下面是一个简单的例子,演示了 Any 的基本用法:

fun printInfo(value: Any) {
    println("Value: $value")
    println("Type: ${value.javaClass.simpleName}")
}

fun main() {
    val stringValue: Any = "Hello, Kotlin!"
    val intValue: Any = 42
    val doubleValue: Any = 3.14

    printInfo(stringValue)
    printInfo(intValue)
    printInfo(doubleValue)
}

延伸: 关于代码中的 value.javaClass.simpleName 作用是 展示类名,对应源码如下:

/**
 * Returns the runtime Java class of this object.
 */
public inline val <T : Any> T.javaClass: Class<T>
    @Suppress("UsePropertyAccessSyntax")
    get() = (this as java.lang.Object).getClass() as Class<T>
/**
 * Returns the simple name of the underlying class as given in the
 * source code. An empty string is returned if the underlying class is
 * {@linkplain #isAnonymousClass() anonymous} or {@linkplain #isUnnamedClass() unnamed}.
 * A {@linkplain #isSynthetic() synthetic class}, one not present
 * in source code, can have a non-empty name including special
 * characters, such as "{@code $}".
 *
 * <p>The simple name of an {@linkplain #isArray() array class} is the simple name of the
 * component type with "[]" appended.  In particular the simple
 * name of an array class whose component type is anonymous is "[]".
 *
 * @return the simple name of the underlying class
 * @since 1.5
 */
public String getSimpleName() {
    if (isUnnamedClass()) {
        return "";
    }
    ReflectionData<T> rd = reflectionData();
    String simpleName = rd.simpleName;
    if (simpleName == null) {
        rd.simpleName = simpleName = getSimpleName0();
    }
    return simpleName;
}

输出结果

Value: Hello, Kotlin!
Type: String
Value: 42
Type: Integer
Value: 3.14
Type: Double

在这个例子中,printInfo 函数接受一个 Any 类型的参数,并打印该值以及其类型。在 main 函数中,我们传递了不同类型的值给 printInfo 函数,展示了 Any 的灵活性。