注:当前文档为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 += 2for (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?
和不安全转换符as
val 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
= listOf(1, 2, null, 4) val intList: List = 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
) @Ann(String::class, Int::class) class MyClass - 枚举; - 其他注解; - 上面已列类型的数组。 - 不能为空;复制代码
类型安全的构建器
类型别名
使用typealias
关键字,不引入新类型前提下,为已知类型或函数的类型名称引入较短的别名叫做类型别名.
-
类
typealias FileTable
= MutableMap >复制代码 -
内部类或嵌套类
class A { inner class Inner } typealias AInner = A.Inner复制代码
-
函数
val f: (Int) -> Boolean = { it > 0 } typealias MyHandler = (Int) -> Boolean ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ val f : MyHandler = { it > 0 }复制代码
本文参考自