重学Kotlin——类型系统

Kotlin中可空类型

常见的几种空判断

?.

安全的调用,当一个值存在时,才会执行它的下一步操作

?:

Elvis操作符,或者合并运算符

!!.

非空断言,用来保证某个变量不为空,除此之外还有 !is  as? 等

原理:Kotlin 在方法参数上标注@Nullable,在实现上,采用if..else来对可空情况进行判断,对比Java8的Optional,兼容性、性能更好,开销更低,语法还简洁。

Either

Either只有两个子类型:Lift、Rigit,如果Either[A, B] 对象包含的是 A 的实例,那么它就是 Left 实例,否则就是 Right 实例。

sealed class Either<A, B> {
    class Left<A, B>(val value: A) : Either<A, B>()
    class Right<A, B>(val value: B) : Either<A, B>()
}

let

public inline fun <T, R> T.let(block: (T) -> R): R = block(this)

调用某对象的let函数,该对象会作为函数的参数,在函数块内可以通过it指代该对象。返回值为函数块的最后一行或这顶return表达式

类型检查

is 关键字

类型智能转换

对于Java中,判断类型 instanceof 后还需要手动强制转换类型,Kotlin中使用 is 判断后自动转换,当然也可以使用 as 关键字转换。配合泛型封装下:

fun <T> cast(original: Any): T? = original as? T

 

Any

Java中Object作为Java类的顶层类型,Kotlin中使用Any作为非空类型的超类。Kotlin不分原始类型。

Any是所有非空类型的跟类型,Any?则是所有类型的跟类型。

Nothing是没有实例的类型,Nothing类型的表达式不会产生任何值,任何返回Nothing的表达式之后的语句都是无法执行的。Kotlin中return、throw等返回值都是Nothing

Kotlin 中 Int 类型等同于 int , Int? 等同于 Integer

 

泛型

优势:

类型检查,能在编译时就帮助检查作物;

更加语义化;

自动类型转换,获取数据时不需要进行类型强制转换;

更加通用化代码

fun main(args: Array<String>) {

    //无法像java一样声明一个list
//    val arrayList = ArrayList()//err

    //水果盘子只能盛Fruit类型的
    val applePlate = FruitPlate(Apple(1.0))
//    val nodlesPlate = FruitPlate(Noodles(1.0))//err

    //只能T : Fruit, T : Ground两种限定
    cut(Watermelon(3.0))
//    cut(Apple(3.0))//err
}

class Plate<T>(val t: T)//盘子

open class Fruit(val weight: Double)//水果

class Apple(weight: Double) : Fruit(weight)//苹果
class Banana(weight: Double) : Fruit(weight)//香蕉

class FruitPlate<T : Fruit>(val t: T)//水果盘子

class Noodles(weight: Double)//面条

interface Ground//刀

class Watermelon(weight: Double) : Fruit(weight), Ground

fun <T> cut(t: T) where T : Fruit, T : Ground {
    print("You can cut me.")
}

泛型擦除

获取所有类型信息的泛型类

open class GenericsToken<T> {
    var type: Type = Any::class.java

    init {
        val superClass = this.javaClass.genericSuperclass
        type = (superClass as ParameterizedType).actualTypeArguments[0]
    }
}

    val gt = object : GenericsToken<Map<String, String>>() {}

匿名内部类在初始化的时候就会绑定父类或父接口的相应信息,这样就能通过获取父类或父接口的泛型类型信息来实现特定需求。可以利用这样的一个类来获取泛型的类型。

也可以使用内联函数获取泛型,只需要加上 reified 关键字

inline fun <reified T> getType() = T::class.java

协变

在定义的泛型类和泛型方法的泛型参数前面加上 out 关键字,表明这个泛型类及泛型方法是协变

类型 A 是类型 B 的子类型,那么Generic<A> 也是 Generic<B> 的子类型,比如 String 是 Any 的子类型,那么 List<String>也是 List<Any> 的子类型。

    //List接口
    public interface List<out E> : Collection<E> 

        //Kotlin中可以实现
        val stringList: List<String> = ArrayList()
        val anyList: List<Any> = stringList

        //而在Java中编译不通过
        List<String> stringList = new ArrayList<>();
        List<Object> objectLis = stringList;//err

 Kotlin中 list 中没有 add 等方法,一旦创建就不能在修改,这就是泛型协变要付出的代价

与Java比较:只能作为消费者,只能读取不能添加

Kotlin:<out T>

Java:<? extends T>

逆变

out 相反, in 关键字代表逆变。A 是类型 B 的子类型,那么 Generic<B> 反过来是 Generic<A> 的子类型

    val numberComparator = Comparator<Number> { n1, n2 ->
        n1.toDouble().compareTo(n2.toDouble())
    }
    val doubleList = mutableListOf(2.0, 3.0)
    doubleList.sortWith(numberComparator)

expect fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): Unit

与Java比较:只能作为生产者,只能添加,读取受限

Kotlin:<in T>

Java:<? super T>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值