kotlin 语法备忘录

1,119 阅读7分钟
原文链接: www.jianshu.com

1 kotlin概述

  • Kotlin 是一种目标平台为 JVM,由 JetBrains 开发的,开源静态类型语言,具有concise(代码简洁)safe(安全)versatile(多平台支持)interoperable(完全兼容java)的特点。

  • Kotlin 是一种面向对象语言。不过它支持高阶函数以及 lambda 表达式和顶层函数。

  • Kotlin 生成的字节码兼容 Java 6 以及更新版本。

  • kotlin避免了java语言的一些弊端,显然kotlin借鉴过java,另外据kotlin作者,kotlin还借鉴了C#,比如扩展。

  • 扩展和函数绝对是kotlin的killing feature。

2 基本类型/变量/流程控制/返回

  • 基本类型与java类似,有:数值,字符,布尔,以及数组。

Char 类表示字符类型,在 Kotlin 中Char不是数值类型。

Array 类表示数组。

  • 变量是值,值有可变与不可变之分:

Kotlin 中使用 var 和 val 来界定 reference 的可变性,尽量保持 reference 是 immutable 的。kotlin会根据变量的赋值自动推断其具体类型。不可变常量如果没有初始化值,则必须声明其具体类型。

  • 变量是值,值还有空与不空之分:

可空变量, Int? ,绕过java的NPE

  • 变量是引用,引用有值类型/引用类型之分:

kotlin中可以给Double类扩展,可以用整型可空Int? ,试想,如果是值类型哪有null的概念。所以Kotlin 中没有原始类型,从语法上看,kotlin中变量类型皆是reference。但其实 Int 类型编译成字节码后是 int 类型(value type)。另见Kotlin 一年の使用报告 - 类型设计

  • 智能类型转换
if ( obj is string ){

//这时obj 自动转换为 String 类型

return obj.length    }
  • 变量的赋值时机,声明时赋值/被访问时赋值(延迟赋值):

lateinit 修饰的变量不能二次赋值;

lateinit 不能修饰 Int、Long 等基本类型,因为它们字节码里是值类型,本身会赋予默认值,所以一修饰就是二次赋值;

  • kotlin里流程控制语句每个分支块都是表达式,表达式是有返回值的。
//if表达式,

val max = if (a > b) a else b

//when表达式

fun cases(obj: Any) {

when (obj) {

1 -> print("one")

"hello" -> print("Greeting")

is Long -> print("Long")

!is Long -> print("Not a string")

else -> print("Unknown")

}

}
  • for 可以对任何具有迭代器的类型的对象进行循环:

有iterator()方法返回迭代类型;

有hasNext()方法返回Boolean;

有next();

for (item in collection)    //集合有迭代器嘛

print(item)
  • 通过 list 或者 array 的索引进行迭代:
for (i in array.indices)

print(array[i])
  • 范围表达式Range
if (x !in 0..array.lastIndex)    print("Out")
  • 函数命名后自动具备标签:
foo outer() {

foo inner() {

return@outer

}

}

2 类/对象/函数

1 类的声明:默认final; open修饰的类表示可继承;sealed修饰的类表示密封类;data修饰的类表示数据类
  • sealed修饰的密封类:作用类似枚举类。密封类的所有子类必须嵌套在密封类的内部。

  • data修饰的数据类:我们经常create a class to do nothing but hold data.数据类会自动根据主构造器生成equals()/hashCode()/toString()/componentN()/copy()。标准类 Pair

  • inner修饰的内部类:内部类持有一个外部类对象。

  • enum修饰的枚举类

2 类可以包含:构造器,init初始化代码块,属性,函数,内部类,对象声明。
  • 构造器

只要主构造函数的所有属性参数都有默认值,编译器就会生成一个无参的构造函数。

  • 属性

属性是变量,变量的特性都适用于它。

属性的getter/setter在kotlin中默认 public。

field 关键词只能用于属性的访问器,就是在setter方法中代表本属性。

lateinit,属性延迟初始化,第一次被访问时才赋值。

Delegated properties委托属性,属性的get set委托给另一个对象,by语句。

委托类提供getter/setter的函数用operator标示。委托类,是一种继承。

属性观察器,var name: String by Delegates.observable

lazy和lateinit特性可以视作基于Delegated properties的一种实现,类似Objective-C中的KVO。

3 函数/函数式思想
  • 函数式语言:函数是头等公民;函数是一种引用类型,叫function type;只有表达式(if else、when 等当作多元运算符);

  • 默认值参数,可以减少重载。可变参数,vararg修饰

  • 局部函数,一个函数在另一个函数内

  • lambda表达式,参数箭头函数体,作为参数传入一个函数。(感觉lambda 表达式是对函数的一种抽象啊,或者说是对匿名函数的一种简化)

  • 高阶函数,参数或返回值是函数或lambda的函数。 Collection 的高阶函数集,如map、filter (对比java8的Stream)

  • 闭包,这个是作用域问题,局部函数访问外部函数的局部变量,形成闭包。

闭包的典型原则是这样:一个输入(参数),一个输出。

所以表象是,内部函数访问外部函数的局部变量。其实是,把一个函数的多个参数转换成一个参数。

因为抽象的时候,多参和单参要统一抽象,那就多参变单参,再加上那个原则,你自然就写成闭包的方式。www.zhihu.com/question/51…

  • 内联函数,它的函数体作为外部函数的函数体的一部分。

高阶函数会形成闭包,那变量调用就会跨越堆内存和函数栈内存(想想java里匿名内部类访问方法局部变量为啥要final),通过内联化inline,可以消除这种开销。 但是,这个时候内联函数的return,直接就把外部函数return了,这叫non-local返回,crossinline修饰可以禁止这种返回。

  • 函数返回什么,不就是说,这个函数是返回类型的一个实例。
4 对象

val customer = Customer("Joe Smith") 没有 new 关键字

对象表达式,相当于匿名内部类,就是对某类做了轻微改变的一个对象。

对象声明,在对象表达式前面有object关键字。这样就闷声地在kotlin里搞了个单例模式。一颗赛艇

对象声明会延迟初始化,对象表达式不会。

伴生对象,一个类里的对象声明且有companion关键字,直接拿类名调用,用起来像java里的静态成员(kotlin没有静态),但其实运行时还是一个实例成员。

解构声明,把一个对象解构成很多变量

5 继承

Kotin 中所有的类都有共同的父类 Any

如果子类没有主构造函数,则必须在每一个构造函数中用 super 关键字初始化基类。

kotlin 中的类默认是 final,接口/抽象类默认是open。open的类可被继承,open的函数可被重写。open class Base(p: Int)

6 扩展/运算符重载
  • Kotlin 支持函数扩展和属性扩展。
fun Int.double() {  
  return this * 2
}
2.double() == 4
  • operator overloading 运算符重载
    用operator关键字修饰扩展函数
class Map<Key, Value> {  
  operator get(key: Key): Value {
    // get and return the value from the map here
  }
}
7 范型

声明处型变:out修饰的只返回不消费,in修饰的只消费而不返回。

reified修饰范型,那在函数内部就可以像一个类一样使用这个范型类型。

3 集合/构建器

可变集合和不可变集合,sort、zip、fold、reduce

构建器(builders)的概念在Groovy社区非常热门。 使用构建器我们可以用半声明(semi-declarative)的方式定义数据。类似的构建器kotlin也可以,格式像DSL,实际上是一个函数,其参数是一个lambda 表达式 。

动态类型,kotlin是静态类型语言,dynamic类型关闭了Kotlin的类型检查,可以在dynamic变量上调用任何属性或任何函数。这样就可以支持与JavaScript的相互调用。


kotlinlang.org/docs/refere…
try.kotlinlang.org/
github.com/antoniolg/B…
github.com/YoungPeanut…