You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin:is检查为何需星投影?Dog<*>与Any?的差异解析

Kotlin泛型is检查中星投影的使用原因

先看你提供的代码(修正了Str为Kotlin合法的String):

class Dog<T: Comparable<T>>(private val name: String, private val weight: T): Comparable<Dog<T>> {
    override fun compareTo(other: Dog<T>): Int {
        return weight.compareTo(other.weight)
    }

    override fun equals(other: Any?): Boolean {
        if (other == null || other !is Dog<*>) return false
        return name == other.name && weight == other.weight
    }
}

你提到的核心问题:为什么equals里的is检查能用Dog<*>,却不能用Dog<Any?>?原因主要有三点:

1. 星投影与具体类型参数的本质区别

  • Dog<*>是星投影,它代表「任意合法类型参数的Dog实例」——不管这个Dog对象创建时用的是什么类型参数(只要符合T: Comparable<T>的约束),is Dog<*>都会判定为true。这正好满足equals的需求:我们只需要确认对方是Dog类的实例,不需要关心它的类型参数具体是什么。
  • Dog<Any?>则是指定了具体类型参数的泛型类型,它仅代表「类型参数为Any?的Dog实例」。但你的Dog类要求类型参数T必须实现Comparable<T>,而Any?并没有实现这个接口,所以实际上不存在合法的Dog<Any?>实例,编译器直接会拒绝把它用于is检查。

2. 类型擦除的影响

Kotlin的泛型是基于类型擦除实现的,运行时无法获取对象的具体泛型类型参数。星投影的设计就是为了应对这种场景:当你不需要关心泛型的具体类型参数,只需要判断是否为某个泛型类的实例时,用星投影就能绕过类型参数的具体校验,匹配所有该泛型类的实例。

而如果用Dog<Any?>这种具体类型参数的写法,编译器会先校验该类型参数是否符合泛型类的约束——显然Any?不满足T: Comparable<T>,所以直接报错,根本到不了运行时检查的阶段。

3. 逻辑合理性

在equals方法中,我们需要判断的是两个对象是否属于同一类(这里是Dog类),而不是「是否属于类型参数为某特定值的Dog类」。星投影正好贴合这个逻辑,而指定具体类型参数反而会缩小匹配范围,甚至因为约束不合法而无法使用。

内容的提问来源于stack exchange,提问作者ntos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:05:18