【修炼内功】[kotlin] 聊一聊泛型的可空性

本文已收录 【修炼内功】跃迁之路

什么?泛型自己也能够是nullable?上来就抛这么个问题实在是不够友好~html

首先回顾,什么是泛型?Oracle Java Tutorialsjava

Introduced in J2SE 5.0, this long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting.

泛型的本质是参数化类型,也就是说操做的数据类型被指定为一个参数。简单来说,泛型就是操做类型的占位符。shell

那,为何要使用泛型?Oracle Java Tutorialssegmentfault

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs. The difference is that the inputs to formal parameters are values, while the inputs to type parameters are types.

泛型的好处是在编译的时候作类型安全检查,而且全部的强制转换都是自动和隐式的,提升代码的重用率。安全

在深刻讨论泛型的可空性以前,首先看一个简单的例子 (kotlin中更多泛型的介绍,以及其与java泛型的区别,能够查看Generics)oracle

fun <T> whoAmI(t: T) {
    val clazz = t::class
    println("I'm $clazz")
}

上面的代码是编译不过的,问题在于
clipboard.pngide

nullable type 'T'是什么鬼?OK,咱们按照提示,为参数t加上!!强制标识为not-null (关于!!的使用,能够查看Null Safety)函数

clipboard.png

WTF~ 哔~ 卒~this

在继续讨论以前,先关注两个概念,type parametertype argument,在一个函数中,前者是函数参数的类型(类型),如translate(java.lang.String, java.lang.String)中的java.lang.String,然后者则是函数调用时传入的具体值(类型),如translate("Hello You!", "zh-cn")中的Hello Youzh-cn,泛型做为一个占位符,占的正是type parameter的位spa

首先简单了解一下argument的可空性,kotlin中控制函数参数值(类属性值等)的nullable是经过?符号实现的,默认均为non-nullable,如如下代码片断是编译不过的

clipboard.png

只有指定参数name为nullable,才能够顺利编译

clipboard.png

一样,对应泛型类,咱们也能够指定nullable及non-nullable的type argument

clipboard.png

从上例中能够看到, null在kotlin中的类型为 Nothing?(kotlin中一切皆为对象)

更多内容请参考 Null Safety

说了这么多,到底什么是泛型的可空性(type argumentnullable)?

上例中,之因此能够将forestA指定为Forest<Tree?>,是由于,每个nullabletype argument都有一个隐式边界Any?,即以下两种类声明彻底等价

// T的隐式边界为Any?
class Forest<T>

// 显示指定T的边界为Any?
class Forest<T : Any?>

// 显示指定T的边界为Tree?
class Forest<T : Tree?>

若是将Forest中的泛型强制指定为non-nullable会发生什么

clipboard.png

什么?不能将nullable的Tree?应用到Forest类了!这是由于Forest类的定义中,咱们强制将泛型的边界指定为了non-nullable的Tree

因此,回到文章的开头,函数whoAmI的错误信息nullable type 'T'指的是哪一个鬼?泛型T的默认边界为Any?,即T : Any?,因此,咱们只须要显示指定T为non-nullable便可

clipboard.png

至此,对于nullablenon-nullabletype parametertype argument是否有所了解?


订阅号