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

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

什么?泛型本身也可以是nullable?上来就抛这么个问题实在是不够友好~

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

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.

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

那,为什么要使用泛型?Oracle Java Tutorials

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)

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

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

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

WTF~ 哔~ 卒~

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

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

只有指定参数name为nullable,才可以顺利编译

同样,对应泛型类,我们也可以指定nullable及non-nullable的type argument

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

更多内容请参考 Null Safety

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

上例中,之所以可以将forestA指定为Forest,是因为,每一个nullabletype argument都有一个隐式边界Any?,即如下两种类声明完全等价

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

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

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

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

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

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

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


你可能感兴趣的:(kotlin,泛型)