星号限制
有时候我们可能对类型参数一无所知,但是我们仍希望安全的使用它。这种安全的方式就是定义一个泛型类型的限制,并且这个限制会把每个实体实例当做这个限制的子类。
Kotlin提供了所谓的星号限制语法:
- 对于Foo<out T>,T是一个共变类型参数,它有个上限类型TUpper,Foo<*>等价于Foo<out TUpper>。这意味着T类型是不可知的,你可以安全的从Foo<*>读取TUpper值。
- 对于Foo<in T>,T是一个逆变的类型参数,Foo<*>等价于Foo<in Nothing>。这意味着当T类型不可知时,你不能向Foo<*>写入任何内容。
- 对于Foo<>,T是一个不可变的类型参数,它有个上限类型TUpper,Foo<*>类型等价于Foo<out TUpper>(读取值),也等价于Foo<in nothing>(写入值)。
如果泛型类型有几个类型参数,那么它们都是可以被单独的限制的。比如,interface Function<in T, out U>可以有以下的星号限制:
- Function<*, String>等价于Function<in Nothing, String>
- Function<Int, *>等价于Function<Int, out Any?>
- Function<*, *>等价于Function<in Nothing, out Any?>
星号限制有点像Java中的默认类型(不传入泛型参数),但是却是安全的。