Kotlin 6 其他

169 阅读5分钟

注:当前文档为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){...}		//倒序

类型检查与转换

  1. 类型检查

    使用is!is操作符对属性类型进行判断.

  2. 类型转换

    编译器跟踪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 自动转换为字符串
         }
    
  3. 智能转换要求 - 编译器不能保证变量在检查和使用之间不可改变

val:

局部变量:不可变,可以智能转换;
全局变量:private或internal,或者检查在声明属性的同一模块中执行。
		open和自定义getter全局变量不能智能转换。

var:

局部变量:如果变量在检查和使用之间没有修改、并且没有在会修改它的 lambda 中捕获;
全局变量:决不可能(因为该变量可以随时被其他代码修改)。
  1. 安全可空转换符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@类名/函数名

  1. 类的成员中,this指代当前类的对象;
  2. 扩展函数(如: fun Int.sum(a:Int):Int{...})或带接收者的函数字面值(如: val sum = fun Int.(other: Int): Int = this + other),指代左侧接收者;

相等性

  1. 引用相等 - 使用 ===!==判断二者是否指向同一个对象.

  2. 结构相等 - 使用==!=判断.

    1. 判断二者是否为空;
    2. 不为空,使用equal(Any?)判断.

操作符符重载

空安全

即抛出空指针异常.可能情况如下:

- 手动抛出;
- java代码空指针;
- 数据未初始化造成的调用问题;
- 使用下文描述的`!!`操作符.

Kotlin中String类型的值不能是null,而String?类型的值可以为null;

空安全之安全调用

  1. 安全调用操作符"?."调用属性

     bob?.department?.head?.name
     //如果任意一个属性(环节)为空,这个链式调用就会返回 null
    
  2. Elvis操作符"?:" - 当且仅当左侧为空时,才会对右侧表达式求值。(throw和return 语句也属于表达式范畴)

     val l: Int = if (b != null) b.length else -1
    
     val l: Int = b?.length ?: -1
    
  3. 空指针操作符"!!" - 表达式中存在时,当该值为空时必抛出空指针异常.

     val l = b!!.length
    
  4. 可空类型的集合转换为非可空集合可以使用**.filterNotNull()实现过滤**

     val nullableList: List<Int?> = listOf(1, 2, null, 4)
     val intList: List<Int> = nullableList.filterNotNull()
    

异常

  1. 主动抛出异常

     throw Exception(" this is a exception ")
    
  2. 被动解决异常,catch,finally均可以省略,但二者至少要存在一个.

     try {
         // 一些代码
     }
     catch (e: SomeException) {
         // 处理程序
     }
     finally {
         // 可选的 finally 块
     }	
    
  3. try-catch是一个表达式

    try 是一个表达式,即它可以有一个返回值。

     val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }
    

    try表达式的返回值是 try 块中的最后一个表达式或者 是**(所有)catch 块中的最后一个表达式**。 finally 块中的内容不会影响表达式的结果。

  4. throw 表达式的返回类型 - Nothing类型

     fun fail(message: String): Nothing {
         throw IllegalArgumentException(message)
     }
     
     val s = person.name ?: fail("Name required")
     println(s)     // 在此已知“s”已初始化
    

注解

注解需要使用annotation关键字,格式如下:

	annotation class Fancy
  1. 注解之元注解 - 修饰注解的注解

     @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 文档中显示的类或方法的签名中。
  2. 注解之使用

     class Foo @Fancy constructor(dependency: MyDependency) {
         //标注主构造必须使用constructor关键字
     
     	@Fancy fun baz(@Fancy foo: Int): Int {
             return (@Fancy 1)
         }
     
     	var x: MyDependency? = null
         @Fancy set
     	//标注属性访问器
     }	
    
  3. 注解之构造参数

    允许的参数类型:

     - 对应于 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
    
     - 枚举;
     - 其他注解;
     - 上面已列类型的数组。
    
     - 不能为空;
    
  4. 注解之Lambda表达式

  5. 注解使用处目标

  6. 注解与java注解

反射

类型安全的构建器

类型别名

使用typealias关键字,不引入新类型前提下,为已知类型或函数的类型名称引入较短的别名叫做类型别名.

  1.  typealias FileTable<K> = MutableMap<K, MutableList<File>>
    
  2. 内部类或嵌套类

     class A {
         inner class Inner
     }
    
     typealias AInner = A.Inner
    
  3. 函数

     val f: (Int) -> Boolean = { it > 0 }
    
     typealias MyHandler = (Int) -> Boolean
    
     ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    
     val f : MyHandler = { it > 0 }
    

本文参考自 Kotlin语言中心站