注:当前文档为Kotlin自学总结,若什么地方含义模糊不清,敬请指教,谢谢:-)。
目录:
- 解构声明
- 集合
- 区间
- 类型检查与转换
- This 表达式
- 相等性
- 操作符重载
- 空安全
- 异常
- 注解
- 反射
- 类型安全的构建器
- 类型别名
解构声明
Kotlin-4.md类的解构声明
集合
区间
区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成
if (i in 1..10){...} //i ∈ [1,10]
for (i in 1 until 10){...} //i ∈ [1,10)
for (i in 1..10 step 2){...} //i += 2
for (i in 10 downTo 1){...} //倒序
类型检查与转换
-
类型检查
使用
is或!is操作符对属性类型进行判断. -
类型转换
编译器跟踪
is判断,在需要时自动插入转换,反向判断.fun demo(x: Any) { if (x is String) { print(x.length) // x 自动转换为字符串 } } // `||` 右侧的 x 自动转换为字符串 if (x !is String || x.length == 0) return // `&&` 右侧的 x 自动转换为字符串 if (x is String && x.length > 0) { print(x.length) // x 自动转换为字符串 } -
智能转换要求 - 编译器不能保证变量在检查和使用之间不可改变
val:
局部变量:不可变,可以智能转换;
全局变量:private或internal,或者检查在声明属性的同一模块中执行。
open和自定义getter全局变量不能智能转换。
var:
局部变量:如果变量在检查和使用之间没有修改、并且没有在会修改它的 lambda 中捕获;
全局变量:决不可能(因为该变量可以随时被其他代码修改)。
-
安全可空转换符
as?和不安全转换符asval x: String = y as String //y可能为null,null不能转换为String,会抛出异常 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓安全转换↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ val x: String? = y as String? ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓转化↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ val x: String? = y as? String
This 表达式
类,函数都存在隐式标签以供this表达式调用,调用方式:this@类名/函数名
- 类的成员中,this指代当前类的对象;
- 扩展函数(如:
fun Int.sum(a:Int):Int{...})或带接收者的函数字面值(如:val sum = fun Int.(other: Int): Int = this + other),指代左侧接收者;
相等性
-
引用相等 - 使用
===或!==判断二者是否指向同一个对象. -
结构相等 - 使用
==或!=判断.- 判断二者是否为空;
- 不为空,使用equal(Any?)判断.
操作符符重载
空安全
即抛出空指针异常.可能情况如下:
- 手动抛出;
- java代码空指针;
- 数据未初始化造成的调用问题;
- 使用下文描述的`!!`操作符.
Kotlin中String类型的值不能是null,而String?类型的值可以为null;
空安全之安全调用
-
安全调用操作符"
?."调用属性bob?.department?.head?.name //如果任意一个属性(环节)为空,这个链式调用就会返回 null -
Elvis操作符"
?:" - 当且仅当左侧为空时,才会对右侧表达式求值。(throw和return 语句也属于表达式范畴)val l: Int = if (b != null) b.length else -1 val l: Int = b?.length ?: -1 -
空指针操作符"
!!" - 表达式中存在时,当该值为空时必抛出空指针异常.val l = b!!.length -
可空类型的集合转换为非可空集合可以使用**
.filterNotNull()实现过滤**val nullableList: List<Int?> = listOf(1, 2, null, 4) val intList: List<Int> = nullableList.filterNotNull()
异常
-
主动抛出异常
throw Exception(" this is a exception ") -
被动解决异常,catch,finally均可以省略,但二者至少要存在一个.
try { // 一些代码 } catch (e: SomeException) { // 处理程序 } finally { // 可选的 finally 块 } -
try-catch是一个表达式
try 是一个表达式,即它可以有一个返回值。
val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }try表达式的返回值是 try 块中的最后一个表达式或者 是**(所有)catch 块中的最后一个表达式**。 finally 块中的内容不会影响表达式的结果。
-
throw 表达式的返回类型 -
Nothing类型fun fail(message: String): Nothing { throw IllegalArgumentException(message) } val s = person.name ?: fail("Name required") println(s) // 在此已知“s”已初始化
注解
注解需要使用annotation关键字,格式如下:
annotation class Fancy
-
注解之元注解 - 修饰注解的注解
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class Fancy@Target指定可以用该注解标注的元素的可能的类型(类、函数、属性、表达式等);@Retention指定该注解是否存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true);@Repeatable允许在单个元素上多次使用相同的该注解;@MustBeDocumented指定该注解是公有 API 的一部分,并且应该包含在生成的 API 文档中显示的类或方法的签名中。
-
注解之使用
class Foo @Fancy constructor(dependency: MyDependency) { //标注主构造必须使用constructor关键字 @Fancy fun baz(@Fancy foo: Int): Int { return (@Fancy 1) } var x: MyDependency? = null @Fancy set //标注属性访问器 } -
注解之构造参数
允许的参数类型:
- 对应于 Java 原生类型的类型(Int、 Long等); - 字符串; - 类(Foo::class);如果需要将一个类指定为注解的参数,请使用 Kotlin 类 (KClass); import kotlin.reflect.KClass annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any?>) @Ann(String::class, Int::class) class MyClass - 枚举; - 其他注解; - 上面已列类型的数组。 - 不能为空;
反射
类型安全的构建器
类型别名
使用typealias关键字,不引入新类型前提下,为已知类型或函数的类型名称引入较短的别名叫做类型别名.
-
类
typealias FileTable<K> = MutableMap<K, MutableList<File>> -
内部类或嵌套类
class A { inner class Inner } typealias AInner = A.Inner -
函数
val f: (Int) -> Boolean = { it > 0 } typealias MyHandler = (Int) -> Boolean ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ val f : MyHandler = { it > 0 }
本文参考自 Kotlin语言中心站